开发者控制台

引用超过65,000个方法造成的编译错误

引用超过65,000个方法造成的编译错误

由于字节码文件中的Dalvid执行限制,引用接近65,000个方法的应用在提交到应用商店时会遇到编译错误。

引用超过65,000个方法造成的构建错误

如果向亚马逊应用商店提交的应用引用了接近65,000个方法,在提交之后,您可能会通过电子邮件或在App Status(应用状态)屏幕中收到以下错误消息:

无法执行dex:方法ID不在[0, 0xffff]中: 65536

转换为Dalvik格式失败: 无法执行dex:方法ID不在 [0, 0xffff] 中: 65536

造成此错误的原因是,对于Dalvik可执行(dex)字节码文件,Android的引用方法数限制为65,535个。有关更多信息,请参阅Android文档中的为方法数超过64000的应用启用multidex

从亚马逊包装器中添加的其他方法

亚马逊会使用代码包装亚马逊应用商店中的每个应用,以便向开发者提供各种报告、分析、DRM和应用更新。此包装器为亚马逊库增加了1627个额外的引用方法,并为每个活动增加了9个额外的方法。由于这些额外的引用方法,如果应用引用了接近65,000个方法,则可能会超过方法限制。

虽然此限制始终存在,但Android 5.0 Lollipop发布后,超过方法引用限制的情况变得司空见惯,因为该版本包含的新特性通常会增加应用可能引用的方法数。 

为了避免此限制,请考虑对引用方法计数并减少应用中的引用方法数。

对引用方法计数

要对应用引用的方法进行计数以及确定应用的哪些部分引用了方法,可以使用GitHub提供的dex-method-counts工具:https://github.com/mihaip/dex-method-counts

减少引用方法的数量

要减少引用方法的数量,请尽可能地删除额外的库和方法。或者,可以在配置中使用ProGuard和-dontoptimize –dontobfuscate,这会在构建时从DEX文件中移除未使用的方法。

如果这些方法不适用于您的应用,请尝试MultiDex方法,这会将classes.dex拆分为多个DEX文件。

可以将MultiDex库与Android Gradle插件配合使用。有关更多信息,请参阅为方法数超过64000的应用启用multidex

使用MultiDex方法时请注意以下事项:

  • 必须使用Gradle进行Android开发。
  • 您会发现,如果不执行几个额外的步骤(下一部分列出),MultiDex无法删除足够多的方法。

可以使用上述dex-method-counts工具来检查生成的classes.dex文件的方法计数。

使用MultiDex库

使用Android 5.0 Lollipop时,Android SDK 21.1.x版和Android支持库21.0.3中会显示一个支持库(称为android-support-multidex.jar)。可在\android-sdk\extras\android\support\multidex\library\libs中找到该支持库。该支持库包含两个新类:MultiDexMultiDexApplication,并简化了MultiDex加载过程。

如果应用专门面向Android 5.0,则无需使用此库,因为Android 5.0提供对次DEX文件的内置支持。但在早期版本中,Android会在类加载器中添加APK归档中的额外.dex文件。该库允许档案为应用主DEX文件的一部分,并管理对其他DEX文件的访问。因此,如果应用面向任何早于Android 5.0的版本,应使用此库。

要为Android 5.0之前的应用实施此解决方案,请执行以下操作:

  1. 确保已将Android构建工具更新到最新版本。至少需要21.1.x或更高版本。
  2. android-support-multidex.jar库添加到项目中。可在\android-sdk\extras\android\support\multidex\library\libs中找到该库。
  3. multiDexEnabled true和Multidex dependency添加到build.gradle文件的buildConfig中,如以下示例所示。

    android {
        compileSdkVersion 21
        buildToolsVersion "21.1.2"
    
        defaultConfig {
            ...
            minSdkVersion 14
            targetSdkVersion 21
            ...
            //启用MultiDex支持。
            multiDexEnabled true
    }
     ...
    }
    dependencies {
        compile 'com.android.support:multidex:1.0.0'
    } 
    
  4. 覆盖android.app.Application,或者在AndroidManifest.xml文件中声明MultiDexApplication类,如以下代码中所示:

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme"
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
    
  5. 如果项目中有任何其他库,请确保对这些库禁用了预索引功能。遗憾的是,--multi-dex选项与已进行DEX预处理的库不兼容。 

    要禁用DEX预处理功能,可以将以下代码添加到app/build.gradle文件中:

    android {
    //  ...
        dexOptions {
            preDexLibraries = false
        }
    }
    
  6. 配置构建指令,以确保MultiDex应用针对亚马逊应用商店和提交流程进行了优化。可执行如下操作:

    1. 手动创建main-dex-list文件。在app/build.gradle文件中,添加以下内容:

      afterEvaluate {
          tasks.matching {
              it.name.startsWith('dex')
          }.each { dx ->
              if (dx.additionalParameters == null) {
                  dx.additionalParameters = []
              }
              dx.additionalParameters += '--multi-dex'
              dx.additionalParameters += "--main-dex-list=$projectDir/<filename>".toString()
          }
      }
      

      此代码使用了两个参数:

      • --multi-dex:在构建过程中启用拆分机制。
      • --main-dex-list:包含必须附加到主DEX文件中的类列表的文件。 

      为了确保MultiDex应用能够正确提交并发布到亚马逊应用商店中,请使用--main-dex-list参数将以下内容放在主.dex文件中:

      • 自定义应用
      • 活动
      • 服务
      • 接收方
      • 提供方
      • 工具
      • 注释
    2. 如果使用的是Studio 0.9.0和Gradle 0.14.2,并让构建工具自动将dx.additionalParameters参数值限制为60,000,则忽略multi-dexmulti-dex-list参数。这应该适用于大多数应用。但是,如果应用中有大量类,可能需要手动将最大数量设置为小于60,000的值,以便正确提交应用到亚马逊应用商店。

确保AndroidX库未混淆

如果使用AndroidX库进行多重索引,请在Proguard文件中添加如下信息以确保AndroidX库未混淆:

-keep class androidx/multidex.** { *; }

其他资源

有关生成main-dex-list的帮助,请参阅以下内容:


Last updated: 2023年10月2日