2019-08-04-Android 64K方法数限制问题总结

1,64k限制的原因

Android的 APK文件本质是一个压缩文件,它里面包含的classes.dex文件是可执行的Dalvik字节码文件,这个dex文件存放的是所有编译过后的Java代码。Dalvik可执行文件规范限制了单个dex文件最多能引用的方法数是65536个。这其中包括了Android Framwork,App自身和第三方库的方法

2,使用MultiDex解决64k限制问题

  • 在Android 5.0之前,系统使用的Dalvik虚拟机来执行Android应用,Dalvik为每个应用生成一个dex文件,默认情况下只生成一个classes.dex文件,为了规避单个dex文件超过64k的问题,我们需要拆分dex文件,拆分后存在classes.dex,classes1.dex ...等多个dex文件。应用启动的时候,会先去加载classes.dex文件,称为主dex文件,然后再依次去加载其他的dex文件,称为从dex
  • 从Android 5.0之后,Android采用Art虚拟机代替Dalvik虚拟机。Art依然是支持多个dex文件,不同的是它会在安装应用期间执行一个预编译操作,将dex预编译成单个.oat文件,在应用启动的时候去加载.oat文件,提升应用启动速度

3,如何避免出现64k方法数限制

  • 当应用需要使用multiDex的时候,不可避免的降低了性能,唯一的办法就是应用的方法数永远低于64k
  • 检查应用的直接和间接第三方库依赖,引入一个第三方库需要综合考虑这个库的体积方法数,性能等等
  • 使用proguard移除无用的代码

4,配置MultiDex

由于各种原因,我们没有办法将方法数降低到64k以下,那么就之后使用Google的MultiDex解决方案。Android的Gradle,首先需要配置Application Molule的build.gradle,使用MultiDex函数库的依赖,同时使用MultiDex

android {
    .....
    defaultConfig {
        .....
        //使用MultiDex支持
        multiDexEnabled true
    }
    .....
}

dependencies {
    .....
    implementation "com.android.support:multidex:1.0.1"
}

然后在自定义的Application类中,做如下声明

protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

4, MultiDex的限制

  • 如果应用的从Dex文件过大,可能出现ANR,原因是Dalvik虚拟机会对所有的Dex文件执行dexopt操作,生成ODEX文件,这个过程非常复杂和耗时
  • 如果App依旧支持Api level 14之前的系统,那么在上线前要严格测试,否则可能出现启动App出现错误
  • 由于Dalvik虚拟机的linearAlloc的限制(Dalvik虚拟机用来加载类的堆内存被硬编码了),在Android 5.0之后使用Art虚拟机,不再有linearAlloc的限制
  • 当引入MultiDex之后,不可避免的有主dex和从dex文件,当应用启动所需要的类都必须放在主Dex文件中,否则会出现NoClassDefFoundError

5,开发阶段优化MultiDex的构建

MultiDex之所以会增加显著的构建时间,原因在于构建系统需要经过复杂的计算决定哪些类要包含到主dex文件中,哪些类可以包含在从Dex文件中

为了解决这个问题,我们可以在gradle中配置开发阶段使用的sdk版本和生产环境使用的sdk版本,提升开发阶段的的效率

productFlavors {
    dev {
        minSdkVersion(21)
    }
    prod {
        minSdkVersion(rootProject.ext.android.minSdkVersion)
    }
}

你可能感兴趣的:(2019-08-04-Android 64K方法数限制问题总结)