针对Android 5.0以下手机的MutilDex解决方案

和大家分享下大型APP处理Multidex的方案。

65K问题的来源:

.Java文件编译生成字节码文件,然后打包生成.dex时会按照类,方法等进行分类,使用IndexMap结构处理。

 

所有的方法都存放在short[] 里, 而short的大小正是65K。 

method的数量远多于class的数量,method的数量会先到65K,class、field同样存在65k的大小限制。

统计时是把系统的,第三方的加上自己的,方法数量的合,都放到这个数组里进行计算, frameworkMethodids + libraryMdthodids + mycodemethodids。

目前存在的解决方案:

坊间存在一种插件的解决方案:

把部分app的功能分离出来做成独立的工程,并把这些功能打包生成apk,在把apk改成.png类型作为资源文件放到asset中,在中工程用到时加载这些“资源”并调用之中的方式,实现了减小主工程方法数、动态加载指定的类完成需要的功能。抽离出来功能作为插件减小了主工程方法数、也带来了新工程的维护成本、和插件工程不能混淆的安全成本、而且跨2个功能的代码维护会变得复杂、调试成本提高。

顶尖的Google提供了另外的一种Multidex方案,简单高效:

1. 编译配置文件build.gradle的 android{}集合中添加 multDexEnable true

2. 编译配置文件build.gradle的dependencies{}集合中添加依赖库  developCompile android.support:multidex:1.0

3. App启动时,oncreate中添加MultiDex.install(context);


如果APP运行在ART虚拟机的设备上,首次启动app加载时间,目前小于100ms,不存在加载慢的问题。ART的优化堪称完美

如果运行在老旧的dalvik虚拟机上,手机app加载时间大约5-20s,会导致ANR。


解决ANR的方法: 

总体思路是:把这个MultiDex.install(this)放到异步线程中加载,同时又要保证在用户使用功能之前,异步线程已经把非主dex加载完成。

从编译到运行起来,发生什么了呢?

1. 编译生成allclasses.jar 生成classes.dex, classes2.dex, .... 多个。

安装阶段:把.dex 优化成classes.odex, 注意,只优化第一个dex文件。

首次运行:

1. dexpath BaseClassLoader.pathlist 类, 把所有的dex都加载。解决了为什么多个dex里的方法也能被正确的index到,不会导致no such method 的crash

2. odex, 这个过程是非常耗时的,如果第二个dex是5-7M的话大约要加载4s, google这个默认方式时间太长,会导致ANR。

这就需要完成2个事情, 1. 把启动需要加载的类放到主dex中, 2. 显示loading界面,保证用户使用之前把dex加载完成。

主dex中的类: 

把这个MultiDex.install(this)放到异步线程中加载,主dex中存放application启动的1直接引用类,所有可能的2入口类,加上3第三方的调用。扫面这些类的直接引用类。统统放到主dex中。

首先在编译打包阶段,在build task中添加一层task, 添加Blacklist.xml自定义的黑名单, 这个名单中的方法对应的类需要添加到主dex中,保证主dex能够加载APP启动时需要的必要的类。

 

balcklist中包含了需要放到主dex中的类的path,addtask的这个task,把blacklist中的类放到了dextask中生成想要的dex。

如何确定哪些类需要放到blcaklist中:

粒度到方法层面,从主activity加载开始,加载了class B的public x 和public y, 则把B的x 和 y方法中,仅x, y方法中import到的类进行分析, 进行回溯添加。

那如何能让工作更高效,能让查找更有保证呢? 请看下篇,基于字节码文件分析.class文件。 

异步加载界面的现实时机:

splash界面,主界面,在收到事件之前进行监听显示load界面。直到异步加载完成所有dex。 

 

其他问题:

主dex不够65k方法,主dex会有多少方法? 生成dex时会一直塞直到塞满65K。

JNI层的回调类,和用到反射的类是需要放到主dex中的,这些BI,库加载都是需要运行就work的。 

 

转载于:https://www.cnblogs.com/doubletrouble/p/5486924.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值