关于 64K 引用限制
随着 Android 平台的持续成长,Android 应用的大小也在增加。当您的应用及其引用的库达到特定大小时,您会遇到构建错误,指明您的应用已达到 Android 应用构建架构的极限。早期版本的构建系统按如下方式报告这一错误:
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
较新版本的 Android 构建系统虽然显示的错误不同,但指示的是同一问题:
trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.
相信这个错误大多是的Android开发者都遇到过,解决办法也是比较简单的,只要引入MultiDexApplication即可。
具体出现这个问题的原因是:
Android打包发布的时候会将所有的class都打包进一个
.dex
文件中。
Android 应用 (APK) 文件包含 Dalvik Executable (DEX) 文件形式的可执行字节码文件,其中包含用来运行您的应用的已编译代码。Dalvik Executable 规范将可在单个 DEX 文件内可引用的方法总数限制在 65,536,其中包括 Android 框架方法、库方法以及您自己代码中的方法。在计算机科学领域内,术语千(简称 K)表示 1024(或 2^10)。由于 65,536 等于 64 X 1024,因此这一限制也称为“64K 引用限制”。
Android 5.0 之前版本的 Dalvik 可执行文件分包支持
Android 5.0(API 级别 21)之前的平台版本使用 Dalvik 运行时来执行应用代码。默认情况下,Dalvik 限制应用的每个 APK 只能使用单个 classes.dex
字节码文件。要想绕过这一限制,您可以使用 Dalvik 可执行文件分包支持库,它会成为您的应用主要 DEX 文件的一部分,然后管理对其他 DEX 文件及其所包含代码的访问。
Android 5.0 及更高版本的 Dalvik 可执行文件分包支持
在5.0以上Android默认支持
Android 5.0(API 级别 21)及更高版本使用名为 ART 的运行时,后者原生支持从 APK 文件加载多个 DEX 文件。ART 在应用安装时执行预编译,扫描 classesN.dex 文件,并将它们编译成单个 .oat 文件,供 Android 设备执行。因此,如果您的 minSdkVersion 为 21 或更高值,则不需要 Dalvik 可执行文件分包支持库。
声明主 DEX 文件中需要的类
为 Dalvik 可执行文件分包构建每个 DEX 文件时,构建工具会执行复杂的决策制定来确定主要 DEX 文件中需要的类,以便应用能够成功启动。如果启动期间需要的任何类未在主 DEX 文件中提供,那么您的应用将崩溃并出现错误 java.lang.NoClassDefFoundError
。
该情况不应出现在直接从应用代码访问的代码上,因为构建工具能识别这些代码路径,但可能在代码路径可见性较低(如使用的库具有复杂的依赖项)时出现。例如,如果代码使用自检机制或从原生代码调用 Java 方法,那么这些类可能不会被识别为主 DEX 文件中的必需项。
因此,如果您收到 java.lang.NoClassDefFoundError
,则必须使用构建类型中的 multiDexKeepFile
或 multiDexKeepProguard
属性声明它们,以手动将这些其他类指定为主 DEX 文件中的必需项。如果类在 multiDexKeepFile
或 multiDexKeepProguard
文件中匹配,则该类会添加至主 DEX 文件。
multiDexKeepFile 属性
您在 multiDexKeepFile 中指定的文件应该每行包含一个类,并且采用 com/example/MyClass.class 的格式。例如,您可以创建一个名为 multidex-config.txt 的文件,如下所示:
com/example/MyClass.class
com/example/MyOtherClass.class
然后,您可以按以下方式针对构建类型声明该文件:
android {
buildTypes {
release {
multiDexKeepFile file 'multidex-config.txt'
...
}
}
}
multiDexKeepProguard 属性
multiDexKeepProguard
文件使用与 Proguard 相同的格式,并且支持整个 Proguard 语法。如需了解有关 Proguard 格式和语法的详细信息,请参阅 Proguard 手册中的 Keep Options 一节。
您在 multiDexKeepProguard
中指定的文件应该在任何有效的 ProGuard 语法中包含 -keep
选项。例如,-keep com.example.MyClass.class
。您可以创建一个名为 multidex-config.pro
的文件,如下所示:
-keep class com.example.MyClass
-keep class com.example.MyClassToo
如果您想要指定包中的所有类,文件将如下所示:
-keep class com.example.** { *; } // All classes in the com.example package
然后,您可以按以下方式针对构建类型声明该文件:
android {
buildTypes {
release {
multiDexKeepProguard 'multidex-config.pro'
...
}
}
}