Android ROM内置应用升级失败

作者: youseewhat | 来源:发表于2019-02-11 23:23 被阅读11次

    内置应用升级失败

    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的,它会尝试重新启动这个应用。

    相关文章

      网友评论

        本文标题:Android ROM内置应用升级失败

        本文链接:https://www.haomeiwen.com/subject/usqceqtx.html