Android ROM內置應用升級失敗

內置應用升級失敗

ROM內置應用通過網絡升級後,應用運行crash,異常日誌顯示一些類、資源文件找不到

java.lang.ClassNotFoundException: Didn't find class

java.lang.NoClassDefFoundError: Failed resolution of

分析

命令過濾log,發現各組件升級安裝過程一切正常

grep -r "dex2oat\|ActivityManagerService\|re-install\|dexopt\|Cdevice\|app包名" *

再次復現查看進程號,發現升級前後進程號沒有變換,意味着AMS沒有回收舊的進程,進程內存沒有加載進來新得apk資源

ps | grep app包名

升級都會殺死原先的進程,沒有殺死是爲什麼?命令查看進程的oom_adj值

cat proce/app進程號/oom_adj

lowmemorykiller根據oom_adj對進程進行管理,策略如下


所以是因爲內置app的application中加了android:persistent="true",導致進程與os的生命週期一直,不被任何組件殺死回收,即便是異常crash、root下kill 命令也不會對內存重的資源重新加載,除非reboot重啓才能讓升級包的apk資源加載到進程中

命令查看app是否使用了該屬性

dumpsys package app包名


關於android:persistent="true"

  • 該屬性只對rom內置應用起作用
  • 副作用比較大,一定要慎用

例如:
1.加了該屬性的app隨系統啓動非常早,如果在app的application中做了網絡請求操作(如域名下發),但此時網絡都還沒有就緒,如果沒有其他的補救措施,就只能升級系統
2.如果app不夠穩定,出現crash,AMS會立馬啓動該app,將陷入crash---啓動的死循環

在系統啓動之時,AMS的systemReady()會加載所有persistent爲true的應用。
persistent應用會頑固地運行於系統之中,從系統一啓動,一直到系統關機。
爲了保證這種持久性,persistent應用必須能夠在異常出現時,自動重新啓動。在Android裏是這樣實現的。每個ActivityThread 中會有一個專門和AMS通信的binder實體——final ApplicationThread mAppThread。這個實體在AMS中對應的代理接口爲IApplicationThread。

當AMS執行到attachApplicationLocked()時,會針對目標用戶進程的IApplicationThread接口,註冊一個 binder訃告監聽器,一旦日後用戶進程意外掛掉,AMS就能在第一時間感知到,並採取相應的措施。如果AMS發現意外掛掉的應用是 persistent的,它會嘗試重新啓動這個應用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章