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包名

問題app

一般的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的,它會嘗試重新啟動這個應用。