随着APP的不断迭代,自身代码在不断增加,同时项目中由于使用了不少的三方库,这时候方法数超过了65536,带来的后果就是编译和打包失败。
当方法数超过65536的时候,会报如下的错误:
The number of method references in a .dex file cannot exceed 64K. Caused by: com.android.tools.r8.utils.AbortException: Error: Cannot fit requested classes in a single dex file (# methods: 68815 > 65536)
65536代表了引用的总数上限,单个Dex文件(Dalvik可执行文件)中最多可以包含65536个方法。
Android应用程序(APK)在Dalvik可执行文件的形式包含可执行的字节码文件(Dex)文件,其中包含已编译的代码。Dex文件最多能包含65536个方法,包括Android框架方法、library方法的总数、和你自己的代码方法总数。因为65536 = 64 × 1024,这一限制被称为“64k引用限制” 。 这个极限就要求我们配置应用程序的构建过程,需要生成多个Dex文件, 所以称为multidex配置。
multi pref 多
Android 5.0 (API leve 21)之前的系统使用Dalvik虚拟机。默认情况下,Dalvik限制一个APK只有一个Dex文件 ,为了绕过这个限制,我们可以使用com.android.support:multidex也就是Android官方为我们提供的解决这个问题的一个库,它成为我们APK的主要Dex文件的一部分,负责管理我们APK访问其他Dex文件和代码。(注意:如果项目minSdkVersion是20或更低,运行到Android 4.4(API leve 20)或者更低版本的设备上时需要禁用AndroidStudio的即时运行)
Android 5.0(API leve 21)和更高的系统使用的runtime是ART ,原生支持从应用的APK文件加载多个Dex文件。ART在安装应用时预编译应用程序,会扫描多个classes(..N).dex文件编译成一个.oat的文件。
尽量避免“64k引用”限制:
选择三方依赖库的时候做好调研工作,选择满足自己功能的并且尽量小的。(建议能用源码的用源码,对于以后自己的定制和维护很有好处)正式打包构建的时候,使用代码混淆器ProGuard混淆移除未使用的代码,也就是不把没有使用的代码打包到我们的APK中。 2 解决“64k引用限制” 第一步:添加配置和依赖(mudule下build.gradle文件)
配置:
defaultConfig {
multiDexEnabled true
}
依赖:
implementation 'com.android.support:multidex:1.0.3'第二步:继承android.support.multidex.MultiDexApplication类
分两种情况,第一种有自己的Application,重写Application中这个方法如下:
public class WanAdroidApplication extends Application {
@Override
protected void attachbaseContext(Contextbase) {
super.attachbaseContext(base);
MultiDex.install(this);
}
}
第二种没有自己的Application,如果我们的APP没有重写过Application类,就直接继承MultiDexApplication,然后在manifest.xml中注册Application即可。
以下是MultiDexApplication的源码:
public class MultiDexApplication extends Application {
public MultiDexApplication() {
}
protected void attachbaseContext(Context base) {
super.attachbaseContext(base);
MultiDex.install(this);
}
}
与此同时可能会报java.lang.OutOfMemoryError: Java heap space错误,那么解决方法是:在mudule的build.gradle中android中添加如下代码:
dexOptions { // 加大java堆内存大小
javaMaxHeapSize "2g" // 这里2g或者4g都可以
}
3 multidex库的一些限制因素
3.1 第二个Dex文件过大问题
Dex文件安装到设备的过程非常复杂,如果第二个Dex文件太大,可能导致应用无响应,此时应该使用ProGuard减小Dex文件的大小
3.2 系统低版本问题由于Dalvik linearAlloc的Bug,应用应该无法在Android 4.0之前的版本启动 ,如果你的应用要支持这些版本就要多执行测试。同样因为Dalvik linearAlloc的限制,如果请求大量内存可能导致崩溃。 Dalvik linearAlloc是一个固定大小的缓冲区。在应用的安装过程中,系统会运行一个名为dexopt的程序为该应用在当前机型中运行做准备。 dexopt使用LinearAlloc来存储应用的方法信息。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB或16MB。当方法数量过多导致 超出缓冲区大小时,会造成dexopt崩溃。Multidex构建工具还 支持指定哪些类必须包含在首个Dex文件中,因此可能会导致某些类库(例如某个类库需要从原生代码访问Java代码)无法使用。
alloc abbr. 分配(allocate, allocation)
总之就是在做低版本兼容的时候可能会崩溃,要多测试。(不过现在基本面向的用户使用的都是4.4以上的系统,这些情况出现的几率大大降低)。
参考https://blog.csdn.net/gongxiaoou/article/details/81281415



