Skip to content

Most visited

Recently visited

navigation

配置方法数超过 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.

这些错误状况都会显示下面这个数字:65,536。这个数字很重要,因为它代表的是单个 Dalvik Executable (dex) 字节码文件内的代码可调用的引用总数。如果您构建的 Android 应用收到了这个错误,那么恭喜您,您有许多代码了!本文介绍如何越过这一限制,继续构建您的应用。

:本文提供的指导将取代 Android Developers 博文 Custom Class Loading in Dalvik(在 Dalvik 中加载自定义类)中提供的指导。

关于 64K 引用限制

Android 应用 (APK) 文件包含 Dalvik Executable (DEX) 文件形式的可执行字节码文件,其中包含用来运行您的应用的已编译代码。Dalvik Executable 规范将可在单个 DEX 文件内可引用的方法总数限制在 65,536,其中包括 Android 框架方法、内容库方法以及您自己代码中的方法。在计算机科学领域内,术语千(简称 K)表示 1024(或 2^10)。由于 65,536 等于 64 X 1024,因此这一限制也称为“64K 引用限制”。

越过这一限制需要您将应用构建流程配置为生成多个 DEX 文件,这种配置称为 Dalvik 可执行文件分包配置。

Android 5.0 之前版本的 Dalvik 可执行文件分包支持

Android 5.0(API 级别 21)之前的平台版本使用 Dalvik 运行时来执行应用代码。默认情况下,Dalvik 限制应用的每个 APK 只能使用单个 classes.dex 字节码文件。要想绕过这一限制,您可以使用 Dalvik 可执行文件分包支持库,它会成为您的应用主要 DEX 文件的一部分,然后管理对其他 DEX 文件及其所包含代码的访问。

:如果您的项目配置时所面向的 Dalvik 可执行文件分包使用的是 minSdkVersion 20 或更低版本,并且您将其部署到运行 Android 4.4(API 级别 20)或更低版本系统的目标设备上,Android Studio 会停用 Instant Run

Android 5.0 及更高版本的 Dalvik 可执行文件分包支持

Android 5.0(API 级别 21)及更高版本使用名为 ART 的运行时,后者原生支持从应用 APK 文件加载多个 dex 文件。ART 在应用安装时执行预编译,扫描 classes(..N).dex 文件,并将它们编译成单个 .oat 文件,供 Android 设备执行。如需了解有关 Android 5.0 运行时的详细信息,请参阅 ART 简介

:如果将应用的 minSdkVersion 设置为 21 或更高,使用 Instant Run 时,Android Studio 会自动将应用配置为进行 Dalvik 可执行文件分包。由于 Instant Run 仅适用于调试版本的应用,您仍需配置发布构建进行 Dalvik 可执行文件分包,以规避 64K 限制。

规避 64K 限制

在将您的应用配置为支持使用 64K 或更多方法引用之前,您应该采取措施减少应用代码调用的引用总数,包括由您的应用代码或包含的内容库定义的方法。下列策略可帮助您避免达到 dex 引用限制:

运用这些技巧可帮助您避免为了在应用中支持更多的方法引用而需要进行的构建配置变更。这些措施还可以减小 APK 的大小,这对带宽成本较高的市场特别重要。

通过 Gradle 配置您的应用进行 Dalvik 可执行文件分包

Android SDK Build Tools 21.1 及更高版本中提供的 Android Plugin for Gradle 支持以 Dalvik 可执行文件分包作为构建配置的一部分。请您务必使用 SDK 管理器将 Android SDK Build Tools 工具和 Android 支持存储区更新至最新版本,然后再尝试配置您的应用进行 Dalvik 可执行文件分包。

将您的应用开发项目设置为使用 Dalvik 可执行文件分包配置需要对您的应用开发项目做几项修改。具体地讲,您需要执行以下步骤:

修改模块级 build.gradle 文件配置以加入支持库和启用 Dalvik 可执行文件分包输出,如下面这段代码中所示:

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.0"

    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...

        // Enabling multidex support.
        multiDexEnabled true
    }
    ...
}

dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

在您的清单中,将 Dalvik 可执行文件分包支持库中的 MultiDexApplication 类添加到 application 元素中。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>

将这些配置设置添加到应用后,Android 构建工具会根据需要构建主 dex (classes.dex) 和辅助 dex(classes2.dex、classes3.dex)。随后构建系统会将它们打包成一个 APK 文件进行分发。

:如果您的应用用途会扩展 Application 类,您可以替换 attachBaseContext() 方法并调用 MultiDex.install(this) 来启用 Dalvik 可执行文件分包。如需了解详细信息,请参阅 MultiDexApplication 的参考文档。

Dalvik 可执行文件分包支持库的局限性

Dalvik 可执行文件分包支持库具有一些已知的局限性,将其纳入您的应用构建配置之中时,您应该注意这些局限性并进行针对性的测试:

优化 Dalvik 可执行文件分包开发构建

Dalvik 可执行文件分包配置大幅增加构建处理时间,因为构建系统必须就哪些类必须包括在主 DEX 文件中以及哪些类可以包括在辅助 DEX 文件中作出复杂的决策。这意味着作为 Dalvik 可执行文件分包开发流程的一部分执行的例行构建通常耗时更长,可能会拖慢您的开发进度。

为了缩短通常耗时更长的 Dalvik 可执行文件分包输出构建时间,您应该利用 Android plugin for Gradle productFlavors(一个开发定制和一个生产定制)在您的构建输出上创建两个变型。

对于开发定制,将最低 SDK 版本设置为 21。在此设置下,使用 ART 支持的格式时可大幅加快 Dalvik 可执行文件分包的生成速度。对于发布定制,将最低 SDK 版本设置为与您的实际最低支持级别一致。此设置生成的 Dalvik 可执行文件分包 APK 可兼容更多设备,但构建时间更长。

以下构建配置示例展示了如何在 Gradle 构建文件中设置这些定制:

android {
    productFlavors {
        // Define separate dev and prod product flavors.
        dev {
            // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
            // to pre-dex each module and produce an APK that can be tested on
            // Android Lollipop without time consuming dex merging processes.
            minSdkVersion 21
        }
        prod {
            // The actual minSdkVersion for the application.
            minSdkVersion 14
        }
    }
          ...
    buildTypes {
        release {
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'),
                                                 'proguard-rules.pro'
        }
    }
}
dependencies {
  compile 'com.android.support:multidex:1.0.0'
}

您完成此配置变更后,可以使用应用的 devDebug 变体,后者集 dev productFlavor 与 debug buildType 的属性于一身。使用此目标创建的将是停用 proguard、启用 Dalvik 可执行文件分包并将 minSdkVersion 设置为 Android API 级别 21 的调试应用。这些设置会使 Android Gradle 插件执行以下操作:

  1. 将应用的每个模块(包括依赖项)构建为单独的 dex 文件。这通常称为预先 dexing。
  2. 将每个 dex 文件加入 APK 时不做任何修改。
  3. 最重要的是,模块 dex 文件将不执行合并操作,因此可以避免为确定主 dex 文件的内容而进行长时间的计算。

这些设置的好处是,可以进行快速的增量式构建,因为只有修改过的模块的 dex 文件才需要重新计算并重新打包到 APK 文件中。这些构建生成的 APK 只能用于在 Android 5.0 设备上进行测试。不过,由于是以定制形式实现配置,您保留了使用与发布相适的最低 SDK 级别和 proguard 设置执行正常构建的能力。

您还可以构建其他变体,包括 prodDebug 变体,该变体虽然构建时间更长,但可用于开发以外的测试。在所示配置内,prodRelease 变体将是最终测试和发布版本。如果您是通过命令行执行 Gradle 任务,可以在标准命令末尾追加 DevDebug(例如 ./gradlew installDevDebug)。如需了解有关利用定制执行 Gradle 任务的详细信息,请参阅 Gradle 插件用户指南

提示:您还可以为每个定制提供一个自定义清单或自定义 application 类,这样您就可以使用支持库 MultiDexApplication 类,或只为需要它的变体调用 MultiDex.install()。

在 Android Studio 中使用构建变体

使用 Dalvik 可执行文件分包时,构建变体可能对构建流程的管理很有帮助。Android Studio 允许您在用户界面中选择这些构建变体。

要让 Android Studio 构建应用的“devDebug”变体,请执行以下操作:

  1. 打开左边栏的 Build Variants 窗口。该选项位于 Favorites 旁边。
  2. 点击构建变体的名称以选择其他变体,如图 1 所示。

图 1. 显示构建变体的 Android Studio 左面板的屏幕截图。

:只有在您使用 Tools > Android > Sync Project with Gradle Files 命令成功完成 Android Studio 与您的 Gradle 构建文件的同步后,才会出现用于打开该窗口的选项。

测试 Dalvik 可执行文件分包应用

编写面向 Dalvik 可执行文件分包应用的仪器测试时,无需进行其他配置。AndroidJUnitRunner 直接支持 Dalvik 可执行文件分包,前提是您使用 MultiDexApplication 或替换您的自定义 Application 对象中的 attachBaseContext() 方法,并调用 MultiDex.install(this) 以启用 Dalvik 可执行文件分包。

您也可以替换 AndroidJUnitRunner 中的 onCreate() 方法:

public void onCreate(Bundle arguments) {
    MultiDex.install(getTargetContext());
    super.onCreate(arguments);
    ...
}

:目前不支持使用 Dalvik 可执行文件分包来创建测试 APK。

This site uses cookies to store your preferences for site-specific language and display options.

Hooray!

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a one-minute survey?
Help us improve Android tools and documentation.