(配置超过64K方法的应用程序)com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536

这是谷歌官方的解释:(翻译过来的)
原文地址(需要翻墙):
https://developer.android.com/studio/build/multidex.html
导致异常以及主要原因(蓝色标记)以及解决方法(红色标记)

 
 
Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536
配置超过64K方法的应用程序

随着Android平台不断增长,Android应用程序的规模也在不断增加。当您的应用程式及其参照的程式库达到一定大小时,您会遇到建立错误,指出您的应用程式已达到Android应用程式建置架构的上限。早期版本的构建系统报告此错误如下:
转换为Dalvik格式失败:
无法执行dex:方法ID不在[0,0xffff]:65536
更多最新版本的Android构建系统显示不同的错误,这是同样问题的指示:
故障写输出:
太多字段引用:131000;最大为65536。
您可以尝试使用--multi-dex选项。
这两个错误条件都显示一个常用的数字:65,536。这个数字很重要,因为它代表单个Dalvik可执行文件(DEX)字节码文件中的代码可以调用的引用的总数。本页说明如何通过启用称为multidex的应用程序配置来超越此限制,允许您的应用程序构建和读取多个DEX文件。
关于64K引用limitAndroid应用程序(APK)文件包含Dalvik可执行文件(DEX)形式的可执行字节码文件,它包含用于运行应用程序的编译代码。 Dalvik Executable规范将单个DEX文件中可以引用的方法的总数限制为65,536!包括Android框架方法,库方法和您自己的代码中的方法。在计算机科学的上下文中,术语Kilo,K表示1024(或2 ^ 10)。因为65,536等于64 X 1024,所以此限制称为“64K参考限制”。
在Android 5.0之前的Android 5.0版本(API级别21)之前的Multidex支持使用Dalvik运行时来执行应用程序代码。默认情况下,Dalvik将应用程序限制为每个APK一个singleclasses.dex字节码文件。为了克服这个限制,您可以使用multidex支持库,它成为应用程序的主要DEX文件的一部分,然后管理对其他DEX文件及其包含的代码的访问。
注意:如果您的项目配置为使用minSdkVersion 20或更低版本的multidex,并且部署到运行Android 4.4(API级别20)或更低版本的目标设备,Android Studio将禁用即时运行。
Multidex支持Android 5.0和更高版本Android 21和更高版本使用一个运行时称为ART本身支持从APK文件加载多个DEX文件。 ART在应用安装时执行预编译,扫描classesN.dex文件并将其编译为单个.oat文件以供Android设备执行。因此,如果您的minSdkVersion为21或更高版本,则不需要multidex支持库。
有关Android 5.0运行时的更多信息,请阅读ART和Dalvik。
注意:使用即时运行时,Android Studio会自动将您的应用程序配置为multidex,当您的应用程序的minSdkVersion设置为21或更高。因为即时运行只适用于您的应用程序的调试版本,所以您仍然需要配置multidex的发行版本以避免64K限制。
避免64K限制在配置应用程序以启用使用64K或更多方法引用之前,您应该采取措施减少应用程序代码调用的引用总数,包括由应用程序代码或包含的库定义的方法。以下策略可帮助您避免达到DEX参考限值:

*检查应用程序的直接和传递依赖关系 - 确保在应用程序中包含的任何大型库依赖关系的使用方式大于添加到应用程序的代码量。一个常见的反模式是包含一个非常大的库,因为一些实用的方法是有用的。减少应用程序代码依赖关系通常可以帮助您避免DEX引用限制。
*使用ProGuard删除未使用的代码 - 启用代码缩小,以便为您的发布版本运行ProGuard。启用缩小功能可确保您不会使用APK传送未使用的代码。

使用这些技术可能会帮助您避免在应用程序中启用multidex,同时还会减少APK的总体大小。
为multidex配置应用程序设置应用项目以使用multidex配置要求您对应用项目进行以下修改,具体取决于您的应用支持的最低Android版本。
如果你的minSdkVersion设置为21或更高,所有你需要做的是在模块级build.gradle文件中将multiDexEnabled设置为true,如下所示:
android {
    defaultConfig {
        ... ...
        minSdkVersion 21
        targetSdkVersion 25
        multiDexEnabled true
    }}
    ... ...
}}
但是,如果您的minSdkVersion设置为20或更低,那么必须使用multidex支持库,如下所示:

*修改模块级build.gradle文件以启用multidex并将multidex库添加为依赖关系,如下所示:
android {
    defaultConfig {
        ... ...
        minSdkVersion 15
        targetSdkVersion 25
        multiDexEnabled true
    }}
    ... ...
}}

依赖关系{
  编译'com.android.support:multidex:1.0.1'
}}

*根据是否覆盖Application类,请执行以下操作之一:
*:
*如果不覆盖Application类,请编辑清单文件以在<application>标记中设置android:name,如下所示:
<?xml version =“1.0”encoding =“utf-8”?>
<manifest xmlns:android =“http://schemas.android.com/apk/res/android”
    package =“com.example.myapp”>
    <应用程序
            android:name =“android.support.multidex.MultiDexApplication”>
        ... ...
    </ application>
</ manifest>

*如果您覆盖Application类,请将其更改为扩展MultiDexApplication(如果可能),如下所示:
public class MyApplication extends MultiDexApplication {...}

*或者如果你重写了Application类,但是不可能改变基类,那么你可以重写attachBaseContext()方法并调用MultiDex.install(this)来启用multidex:
public class MyApplication extends SomeOtherApplication {
  @覆盖
  protected void attachBaseContext(Context base){
     super.attachBaseContext(context);
     Multidex.install(this);
  }}
}}



现在当你构建你的应用程序,Android构建工具构建一个主要的DEX文件(classes.dex)和支持DEX文件(classes2.dex,classes3.dex,等等)根据需要。构建系统然后将所有DEX文件打包到您的APK。
在运行时,multidex API使用特殊的类加载器来搜索您的方法的所有可用DEX文件(而不是仅在mainclasses.dex文件中搜索)。
multidex支持库的限制multidex支持库有一些已知的限制,您应该注意并测试何时将它合并到您的应用程序构建配置:

*在启动过程中将DEX文件安装到设备的数据分区上很复杂,如果辅助DEX文件较大,可能导致应用程序无响应(ANR)错误。在这种情况下,您应该使用ProGuard应用缩减代码以最小化DEX文件的大小并删除未使用的代码部分。
*由于Dalvik linearAlloc错误(问题22586),使用multidex的应用程序可能无法在运行低于Android 4.0(API级别14)的平台的设备上启动。如果您的API级别低于14,请务必使用这些版本的平台进行测试,因为您的应用在启动时或加载特定类别的组时可能会遇到问题。代码缩减可以减少或可能消除这些潜在问题。
*由于Dalvik linearAlloc限制(Issue78035),使用multidex配置进行非常大的内存分配请求的应用程序可能在运行时崩溃。 Android 4.0(API级别14)中的分配限制已增加,但在Android 5.0(API级别21)之前的Android版本中,应用仍可能达到此限制。

声明主DEX文件中所需的类在构建multidex应用程序的每个DEX文件时,构建工具执行复杂的决策,以确定主DEX文件中需要哪些类,以便您的应用程序可以成功启动。如果在初始DEX文件中没有提供启动期间所需的任何类,那么您的应用程序会崩溃,并返回错误java.lang.NoClassDefFoundError。
这不应该发生在直接从应用程序代码访问的代码上,因为构建工具会识别这些代码路径,但是当代码路径不太明显时,例如当您使用的库具有复杂的依赖关系时,就会发生这种情况。例如,如果代码使用内省或从本机代码调用Java方法,那么这些类可能不会被识别为主DEX文件中的必需。
因此,如果您收到java.lang.NoClassDefFoundError,那么必须在生成类型中使用multiDexKeepFile属性声明它们,从而在主DEX文件中手动指定这些附加类。您在此处指定的文件应该在每行中包含一个类,在formatcom / example / MyClass.class中。例如,您可以创建一个名为dex.keep的文件,如下所示:
com / example / MyClass.class
com / example / MyOtherClass.class
然后,您可以如下为生成类型声明该文件:
android {
    buildTypes {
        发布 {
            multiDexKeepFile文件('dex.keep')
            ... ...
        }}
    }}
}}
记住,Gradle读取相对于build.gradle的路径,因此如果dex.keep与build.gradle文件在同一目录中,上面的示例工作。
在开发构建中优化multidex multidex配置需要显着增加构建处理时间,因为构建系统必须做出关于哪些类必须包含在主DEX文件中以及哪些类可以包含在辅助DEX文件中的复杂决策。这意味着使用multidex的增量构建通常需要更长的时间,并且可能会减慢您的开发过程。
要减少multidex输出的较长构建时间,请使用productFlavors创建两个构建变体:一个开发风格和一个具有不同minSdkVersion值的发布风格。
对于开发风格,将minSdkVersion设置为21.此设置启用称为预先dexing的构建功能,使用仅适用于Android 5.0(API级别21)或更高版本的ART格式,可以更快地生成multidex输出。对于发行版本,请将minSdkVersion设置为适合您实际的最低支持级别。此设置会生成与更多设备兼容的multidex APK,但需要更长时间才能生成。
以下构建配置示例演示如何在Gradle构建文件中设置这些类型:
android {
    defaultConfig {
        ... ...
        multiDexEnabled true
    }}
    产品简介{
        dev {
            //启用pre dexing产生一个可以测试的APK
            // Android 5.0+,没有耗时的DEX构建过程。
            minSdkVersion 21
        }}
        prod {
            //生产版本的实际minSdkVersion。
            minSdkVersion 14
        }}
    }}
    buildTypes {
        发布 {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }}
    }}
}}
依赖关系{
    编译'com.android.support:multidex:1.0.1'
}}
完成此配置更改后,可以使用应用程序的devDebug变量进行增量构建,其中结合了thedev产品flavor和调试构建类型的属性。这创建一个可调试的应用程序,启用multidex和proguard禁用(因为minifyEnabled isfalse默认情况下)。这些设置导致Gradle的Android插件执行以下操作:

1.执行pre dexing:将每个应用程序模块和每个依赖项构建为单独的DEX文件。
2.在APK中包含每个DEX文件,不进行修改(没有缩小代码)。
最重要的是,模块DEX文件不组合,因此避免了长时间运行的计算以确定主DEX文件的内容。

这些设置导致快速增量构建,因为在后续构建期间只重新计算并重新打包修改模块的DEX文件。但是,来自这些版本的APK只能用于在Android 5.0设备上测试。但是,通过将配置实现为一种风格,您可以保留使用适当的最低API级别和ProGuard代码收缩执行正常构建的能力。
您还可以构建其他变体,包括prodDebug变体生成,这需要更长的构建,但可以用于在开发外测试。在所示的配置中,prodRelease变量将是最终测试和发行版本。有关使用构建变体的详细信息,请参阅配置构建变体。
提示:现在您针对不同的multidex需求有不同的构建版本,您还可以为每个版本提供不同的清单文件(因此只有针对API级别20和更低版本的版本更改了<application>标记名称),或者创建不同的应用程序子类(所以只有一个为API级别20和更低版本扩展MultiDexApplication类或调用MultiDex.install(this))。
测试multidex应用程序在为multidex应用程序编写测试测试时,不需要其他配置。 AndroidJUnitRunner支持multidex开箱即用,只要在自定义Application对象中使用MultiDexApplication或覆盖attachBaseContext()方法,并调用MultiDex.install(this)以启用multidex。
或者,您可以覆盖AndroidJUnitRunner中的onCreate()方法:
public void onCreate(Bundle arguments){
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
    ... ...
}}

注意:目前不支持使用multidex创建测试APK。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值