内置应用升级失败
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的,它会尝试重新启动这个应用。
网友评论