【MultiDex.install引发低端机ANR】为什么64K?字节码决定

 

问题:低端机首次启动时间久,极大概率触发ANR

分析:

  1. ANR是什么?
  • 现象:App上弹出提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close
  • 官方解释:Application Not responding,应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR 
  • 主线程执行启动过程中,用户UI操作,未在指定时间内被处理。

 http://gityuan.com/2017/01/01/input-anr/ 

 

2. 启动过程做了什么?

 

该图是进入项目代码层面后,执行代码的顺序。

 

attachBaseContext: 可控制第一个步骤, 执行MultiDex.install()

首次启动:Dalvik虚拟机对classes.dex执行dexopt操作,生成odex文件【超时】

非首次启动:直接从cache读取

https://juejin.im/entry/5705b2712e958a0057a5f735 

 

 

3. 为什么只有低端机会中招?

Android 5.0及以上版本:ART模式,预先编译,app安装之后进行预编译(pre-compilation) ,如果这时候发现了classes(..N).dex文件的存在就会将他们最终合成为一个.oat的文件

Android 5.0以下版本:安装时仅处理主dex,首次启动时执行dexopt操作,处理附属dex文件

 

4. MultiDex  

Android官网:Davlik中限制了单个dex中可引用方法总数不能超过64K,超过就必须要拆分为多个dex

抛出异常的出处,打包过程某方法:

 

延展:为什么是64K?

  • 代码的终极走向是被编译为机器码,被机器执行
  • 引用方法等会被存入索引表,索引字段存储于机器,机器字节码位数限制可建索引项数。dalvik bytecode 

如方法引用索引,16位,64K=2^16 

 

https://source.android.com/devices/tech/dalvik/dalvik-bytecode 

特别感谢:http://jayfeng.com/2016/03/10/%E7%94%B1Android-65K%E6%96%B9%E6%B3%95%E6%95%B0%E9%99%90%E5%88%B6%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83/ 

 

解决:

高端机型(java.vm.version>”2.0.0”表明虚拟机运行环境为ART):直接执行MultiDex.install()

低端机型:增加初始化界面,LoadResActivity中异步执行加载

特别注意的是:当activity到后台时,轮询不启动异步执行

 

借用网上一张流程图,基本说明如下:基本流程类似,启动检测时机略有区别,启动过程单独起进程检测是否安装过

 

posted @ 2019-01-02 15:57  QA小虾  阅读(845)  评论(0编辑  收藏  举报