【问题标题】:Application too big? Unable to execute dex: Cannot merge new index into a non-jumbo instruction应用太大?无法执行 dex:无法将新索引合并到非巨型指令中
【发布时间】:2014-06-24 23:40:20
【问题描述】:

我在编译我的应用程序时收到以下错误:

[2014-05-07 21:48:42 - Dex Loader] Unable to execute dex: Cannot merge new index 65536 into a non-jumbo instruction!

我正处于如果我在包中的任何位置声明一个新方法,我会收到此错误。如果我不这样做,应用程序就会编译。

我想知道这个错误究竟是什么意思。我的应用程序很大,但我认为它没有那么大!所以:

  • 这个错误是否意味着我的方法太多了?民众?静止的?包裹?会员?
  • 它与我的根包的方法/成员有关,还是与包含的 JAR 库有关?
  • 有没有办法获得有关此的更多调试信息?

我已经知道在 SO 的类似问题中解决的“巨型”启用标志,但是,我认为巨型模式在我的目标 API 级别 (ICS) 上不可用。

【问题讨论】:

标签: android linker-errors dex


【解决方案1】:

一些有趣的观察。如果您有多口味项目,可能会出现相同的错误。这很令人困惑。结果我尝试使用通用命令运行应用程序:gradlew installDebug。当我改变命令行看起来这个问题已经消失了。不要忘记用实际的替换 Flavor 部分。

gradlew installFlavorDebug

【讨论】:

    【解决方案2】:

    您的错误在于单个 dex 文件中的字符串数量(方法、成员等)。

    您需要使用 jumbo in dex 编译您的应用程序:

    dex.force.jumbo=true
    

    在project.properties

    这会增加 dex 文件中字符串的限制。你的项目可能会编译。

    同样对于 jumbo set,64K 仅适用于单个 dex 中的方法的另一个限制。如果将来遇到此限制,则需要删除一些依赖项。

    更新:使用 Gradle 构建: 在 Gradle 中,您也可以在 build.gradle 文件中启用 jumboMode:

    dexOptions {
        jumboMode = true
    }
    

    检查: Android Build: Dex Jumbo Mode in Gradle

    同样使用 Gradle,您可以使用 multidex 构建来避免 方法的 64K 限制,教程在这里: https://developer.android.com/tools/building/multidex.html

    【讨论】:

    • 在 ICS 中启用了 jumbo,所以这可以帮助你:)
    • 不幸的是,添加标志后它对我不起作用,因为我认为我达到了声明方法而不是字符串的限制。这就是为什么我想要获取有关每个 JAR 的方法数量的调试信息的原因。
    • 感谢您的链接!我还发现,如果我使用 ANT 而不是从 Eclipse IDE 编译项目,方法计数会打印到控制台。
    【解决方案3】:

    对于 gradle 构建,只需将 dexOptions 添加到 build.gradle 中即可启用 jumbo 模式:

    android {
        dexOptions {
            jumboMode = true
        }
    }
    

    记得在你的新建筑之前运行“gradle clean”。

    【讨论】:

      【解决方案4】:

      看起来问题是因为您项目中的所有类文件和 JAR 文件在 DEXing 之前打包在一起。这可能并不完全正确,但事实证明,在我们的项目中控制这一点的任何方式都非常困难。即使删除最初导致此问题的内容,清理和重建也无法以一致的方式为我们解决问题。

      因此,我们借此机会将项目切换到 Android Studio,并通过启用 ProGuard 进行调试构建来解决问题。更准确地说,我们只使用 ProGuard 处理链的收缩阶段。

      Gradle 可以很容易地为调试构建打开 ProGuard:

      buildTypes {
          debug {
              runProguard true
              proguardFile 'proguard-project-debug.txt'
          }
      }
      

      这是我们使用的调试 ProGuard 配置:

      -keep class com.your.code.**
      # Use -keep to explicitly keep any other classes shrinking would remove
      -dontoptimize
      -dontobfuscate
      -ignorewarnings
      

      这确实增加了项目的构建时间,但好的一面是调试器仍然可以工作。

      我能想到的唯一更快的选择是手动删除任何 JAR 文件中未使用的类文件。但这不仅很难做到,而且当您以后想要使用库的稍大部分时也很不方便。

      我希望这可以帮助其他解决此问题的开发人员。也许将来谷歌可以改进默认进行这种修剪的编译器。我们的 APK DEX 文件从 8MB 变为 2.9MB。

      较新的 gradle (1.0.0+) 版本

      在较新版本的 Android Studio (1.0+) 中,捆绑的 Gradle 得到了更新。构建机制的工作方式发生了一些变化,因此您的项目 Gradle 文件现在可以利用 minifyEnabled 和 shrinkResources 参数。当前版本是 1.1.0。

      在 Android 等快速发展的平台上跟上变化需要付出努力,但通常会获得新功能、工具和更快的构建时间。因此,更新 Android Studio 并(仔细)更新您的项目是值得您投入时间的。

      buildTypes {
          debug {
              proguardFile 'proguard-project-debug.txt'
              minifyEnabled true
              shrinkResources true
          }
      }
      

      【讨论】:

      • +1 是为调试构建打开 proguard 的绝佳解决方案。使用-dontoptimize 和-dontobfuscate 构建调试版本的额外延迟不会太多。不幸的是,在我当前的项目中,我无法切换到 Android Studio,因为它的变化太大了,但对于即将到来的项目,这可能是要走的路。
      【解决方案5】:

      这与项目中包含的库的方法数量有关。例如,如果您的应用中有跟踪功能,那么仅 Google Analytics(分析)就有约 7000 种方法。 在我的一个项目中使用 Lombok(2MB 的 JAR)给了我这些问题。解决了摆脱这个库的问题。

      【讨论】:

      • 感谢您的回复!你知道是否有办法知道我包含的 JAR 和项目的方法数量?一种详细的汇编或类似的东西?
      • 也许你可以试试this thread接受的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      • 2014-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 2012-10-12
      相关资源
      最近更新 更多