【MultiDex.install引发低端机ANR】为什么64K?字节码决定
问题:低端机首次启动时间久,极大概率触发ANR
分析:
- 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
解决:
高端机型(java.vm.version>”2.0.0”表明虚拟机运行环境为ART):直接执行MultiDex.install();
低端机型:增加初始化界面,LoadResActivity中异步执行加载
特别注意的是:当activity到后台时,轮询不启动异步执行
借用网上一张流程图,基本说明如下:基本流程类似,启动检测时机略有区别,启动过程单独起进程检测是否安装过