--main-dex-list中的类太多,超出了主要的dex容量

时间:2015-09-22 15:35:24

标签: android-gradle dex

我尝试运行检测测试用例,但在dex转换时遇到以下错误 意外的顶级例外:

com.android.dex.DexException: Too many classes in --main-dex-list, main dex capacity exceeded
        at com.android.dx.command.dexer.Main.processAllFiles(Main.java:494)
        at com.android.dx.command.dexer.Main.runMultiDex(Main.java:334)
        at com.android.dx.command.dexer.Main.run(Main.java:244)
        at com.android.dx.command.dexer.Main.main(Main.java:215)
        at com.android.dx.command.Main.main(Main.java:106)

:App:dexDebug FAILED

如何在gradle中解决此问题?

3 个答案:

答案 0 :(得分:23)

让我们先了解问题:

在Lollipop之前的设备上,框架只加载了主要的dex。要支持多dex应用程序,您必须使用所有辅助dex文件显式修补应用程序类加载器(这就是您的Application类必须扩展MultiDexApplication类或调用MultiDex#install)的原因。

这意味着您的应用程序的主dex应包含在类加载器修补之前可能可访问的所有类。

如果您的应用程序代码在成功修补应用程序类加载器之前尝试引用打包在某个辅助dex文件中的类,您将收到java.lang.ClassNotFoundException

我是documented here插件如何决定应该在main-dex中打包哪些类。
如果这些类引用的方法总数超过65,536限制,则构建将失败,并显示Too many classes in --main-dex-list, main dex capacity exceeded错误。

我可以为这个问题考虑三种可能的解决方案:

  1. (最简单的解决方案,但不适合大多数人使用 应用程序)将minSdkVersion更改为21.
  2. 缩小您的应用程序代码。之前已多次讨论过此问题(请参阅herehere)。
  3. 如果以上解决方案都不适合您,您可以尝试使用my workaround来解决此问题 - 我修补Android gradle插件,不在主dex中包含Activity类。它有点笨拙,但对我来说效果很好。
  4. Android错误跟踪器中有关于此错误的an issue。希望工具团队能够尽快提供更好的解决方案。

    更新(2016年4月27日)

    Gradle插件的2.1.0版允许过滤main-dex列表类 警告:这是使用不受支持的api,将来会被替换。

    例如,要排除您可以执行的所有活动类:

    afterEvaluate {
      project.tasks.each { task ->
        if (task.name.startsWith('collect') && task.name.endsWith('MultiDexComponents')) {
          println "main-dex-filter: found task $task.name"
          task.filter { name, attrs ->
            def componentName = attrs.get('android:name')
            if ('activity'.equals(name)) {
              println "main-dex-filter: skipping, detected activity [$componentName]"
              return false
            } else {
              println "main-dex-filter: keeping, detected $name [$componentName]"
              return true
            }
          }
        }
      }
    }
    

    您还可以查看演示此问题的example project(并应用上述过滤)。

    更新2(2016年7月1日)

    Gradle插件版本2.2.0-alpha4(带有build-tools v24)最终通过reducing multidex keep list to a minimum解决了这个问题。
    不应再使用2.1.0中不支持(和未记录)的过滤器。我已经更新了我的sample project,证明现在构建成功,没有任何自定义构建逻辑。

答案 1 :(得分:21)

解决此问题的另一种方法是从主DEX文件中删除带有运行时注释的类:

android {

    dexOptions {
        keepRuntimeAnnotatedClasses false
    }

}

这对于使用依赖注入框架的应用程序特别有用,因为即使Dagger注释通常也会保留在运行时。

答案 2 :(得分:-3)

你有两个选择。

  1. 使用ProGuard删除多少方法
  2. 使用multidex功能
  3. 我的建议 - 与ProGuard一起使用,它只需要对源代码进行零更改