2019-10-20 [M1.multidex问题]

2019-10-20  本文已影响0人  妖怪青同学

[1] multidex问题

1.问什么会用 multidex

android dex使用shot作为方法索引

shot 2^16=65536

1.1 Dalvik 和 Art

Android 5.0 之前

Android 5.0(API 级别 21)之前的平台版本使用 Dalvik 运行时来执行应用代码。默认情况下,Dalvik 限制应用的每个 APK 只能使用单个 classes.dex 字节码文件。要想绕过这一限制,您可以使用multidex,然后管理对其他 DEX 文件及其所包含代码的访问。

Android 5.0 及更高版本 默认支持分包dex 加载

Android 5.0(API 级别 21)及更高版本使用名为 ART 的运行时,后者原生支持从 APK 文件加载多个 DEX 文件。ART 在应用安装时执行预编译,扫描classesN.dex 文件,并将它们编译成单个 .oat 文件,供 Android 设备执行。因此,如果您的 minSdkVersion为 21 或更高值,则不需要 Dalvik 可执行文件分包支持库。

1.2 实现原理

class编译进不同的classes.dex文件中,一般情况下,一个APK文件中只包含了一个classes.dex文件。分包之后就存在一个主的classes.dex,多个副的classes2.dex,classes3.dex…
在要启动程序时,Android会先去加载主的classes.dex,然后在程序启动后再去加载其它副的dex。那哪些class应该被编译到主的classes.dex中呢?

1.3 Proguard

移除多余方法 , 只减缓问题,不根本解决

如果您的minSdkVersion 设置为 21 或更高值,您只需在模块级 build.gradle 文件中将multiDexEnabled 设置为 true,如此处所示:
android {
    defaultConfig {
        ...
        minSdkVersion 21 
        targetSdkVersion 26
        multiDexEnabled true
    }
    ...
}
但是,如果您的 minSdkVersion 设置为 20 或更低值,则Gradle 构建脚本依赖关系标识符如下所示:

compile 'com.android.support:multidex:1.0.2'

1.4 multidex的问题

其实你不知道MultiDex到底有多坑

文档还写明了multiDex support lib 的局限。瞄一下是什么:

1.在应用安装到手机上的时候dex文件的安装是复杂的(complex)有可能会因为第二个dex文件太大导致ANR。请用proguard优化你的代码

2.使用了mulitDex的App有可能在4.0(api level 14)以前的机器上无法启动,因为Dalvik linearAlloc bug(Issue 22586) 。请多多测试自祈多福。用proguard优化你的代码将减少该bug几率。呵呵

3.使用了mulitDex的App在runtime期间有可能因为Dalvik linearAlloc limit (Issue 78035) (由于classes太多方法太多超过这个linearAlloc 的限制) Crash。该内存分配限制在4.0版本被增大,但是5.0以下的机器上的Apps依然会存在这个限制。

4.主dex被dalvik虚拟机执行时候,哪些类必须在主dex文件里面这个问题比较复杂。build tools 可以搞定这个问题。但是如果你代码存在反射和native的调用也不保证100%正确。呵呵

A:所以有的低端机 4.几的由于虚拟机分配内存很小导致 分包后依然dex依然爆炸(那么gradle中限制每个dex的方法数,多分几个dex)

Multidex记录二:缺陷&解决 ..在Android版本不同分别经历了4M/5M/8M/16M限制,目前主流4.2.x系统上可能都已到16M, 在Gingerbread或者以下系统LinearAllocHdr分配空间只有5M大小的, 高于Gingerbread的系统提升到了8M。Dalvik linearAlloc是一个固定大小的缓冲区。在应用的安装过程中,系统会运行一个名为== ==dexopt的程序为该应用在当前机型中运行做准备 。==dexopt使用LinearAlloc来存储应用的方法信息==。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB或16MB。当方法数量过多导致超出缓冲区大小时,会造成dexopt崩溃。

B:还有反射或者native调用的方法不在主dex中 导致 NoClassDefFoundError

C:主dex的生成

先依据manifest里注册的组件生成一个 main-list,然后把这list里的classes所依赖的classes找出来,把他们打成classes.dex就是主dex

关于Android 64K引发的MultiDex你想知道的都在这里:一场由启动黑屏引发的惨案

其实你不知道MultiDex到底有多坑

上一篇下一篇

猜你喜欢

热点阅读