Android:我的应用程序太大,并提供“无法执行dex:方法ID不在:65536”?

我正在尝试将我的应用程序与Box,Dropbox和Google Drive集成在一起。 所有这些服务都需要一些第三方的jar子。 此外,我的应用程序已经需要一些第三方的jar子。 现在,当我尝试从eclipse运行我的应用程序时,出现以下错误:

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

看来,这个错误发生是因为我的应用程序有太多的方法。 我相当肯定这些方法的大部分来自第三方jar,所以试图通过简化我的代码来解决这个问题是不现实的。 我在网上find了这两个build议。

  1. dex.force.jumbo=true添加到project.properties(并使用adt版本21)。 我这样做,但仍然得到错误。

  2. 按照下面的说明使用多个dex文件: http : //android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html 。 这似乎是唯一的select,但我不明白它是如何适用于我的情况。 问题是像Drive这样的服务有太多的依赖关系。 这个解决scheme是不是要求我修改驱动源来引用它的依赖时使用拐点? (这显然不是一种select)。

  3. 使用proguard缩小删除不使用的代码/方法。 用proguard导出我的应用程序确实有效,文档服务集成按照预期在> 4.0设备上工作。 但是,在2.3设备上testing时会引发classnotfound错误。

所以,我希望在这个问题上有一些build议。 选项2是我的情况的解决scheme吗? 我应该考虑另一个解决scheme吗?

您也可以将其中的一个或多个作为主要应用程序的插件开发,可以单独下载APK。 该APK会暴露主应用程序将使用的一些组件 – 因为我不知道你与这些服务集成的性质,所以我无法对此做出更具体的build议。 您将使用您自己的signature级别自定义<permission>来保护两个应用程序之间的通信。 而且,作为奖励,如果使用第三方库添加了额外权限的要求,则只需要插件APK中的这些权限,即可使主APK保持较小。

Dalvik VM每个dex文件最多可以有65536个方法,因为字节码指令集无法引用需要多于16位的方法号(正如注释中的@danfuzz所指出的那样)。

尽pipe可以使用多个dex文件来解决这个问题 ,但是Facebook 发现了另一个可以在应用程序中部署的修复程序来解决问题。

***新****所有其他答案现在已经过时。 这是新的修复程序

Android 5.0及更高版本

Multi-dex支持自动包含在内。 从文档:

Android 5.0及更高版本使用名为ART的运行时,它本身支持从应用程序APK文件加载多个dex文件。 ART在应用程序安装时执行预编译,扫描类(.. N).dex文件,并将它们编译成一个.oat文件供Android设备执行。 有关Android 5.0运行时的更多信息,请参阅介绍ART。

低于Android 5.0

只需将Android mult-dex支持工具添加到您的Gradle版本即可:

 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' } 

看到vm / LinearAlloc.c,你可以find这个代码:( Android 2.3.3下的5MiB,Android 4.0之后的8MiB作为我的调查)

#define DEFAULT_MAX_LENGTH(5 * 1024 * 1024)

LinearAllocHdr * pHdr;

pHdr-> mapLength = DEFAULT_MAX_LENGTH;

我猜想“Facebook修复”是通过使用本地C指针来编辑这个内存。 恕我直言,LinearAlloc问题和这种方法ID问题是不同的事情。

我最近面临这个问题。 在search了一些更详细的实现之后,我意识到除了:

  • 好,但现在Gradle已经过时了: http : //android-developers.blogspot.co.il/2011/07/custom-class-loading-in-dalvik.html
  • 没有太多的细节,但是对于如何做到的模糊的想法: https : //www.facebook.com/notes/facebook-engineering/under-the-hood-dalvik-patch-for-facebook-for-android/10151345597798920

我意识到问题不一定是我的代码中有太多的方法,而是我的代码和其他库的完整的dex是问题。 所以,如果我可以编译我的代码,而不是将它们包含在classes.dex ,然后将这些库单独分开,然后在运行时将它们放在一起,就可以工作。 剩下的唯一问题就是Facebook的类加载器,Facebook提到了这个问题。

因此,通过一些反思和一些Groovy代码,我想我想出了一个相对稳定的方法来将库和应用程序代码打包到单独的dex文件中。

https://gist.github.com/nickcaballero/7045993

大部分碰到65k方法限制的问题与在您的应用程序中使用乳沟Google Play服务有关。 最近,使用它时可以获得更多的粒度。

遵循本指南 ,您只能使用您需要的零件。 可能这会解决问题,避免一些黑魔法技巧,或使用multiDex。 例如,如果您只需要在您的应用中使用Google地图(并且您没有使用广告,钱包,谷歌磨损,分析等),则使用整个依赖关系是浪费时间/空间。 你可以这样使用它:

 compile com.google.android.gms:play-services-base:6.5.87 compile com.google.android.gms:play-services-maps:6.5.87 

您可以在此链接中阅读“零件”的完整列表

这里是我写的一个脚本,用于计算每个jar(总共)中特定文件夹的方法数量。

一旦你计算的方法,你可以专注于重构和删除重型库。

您需要启用对此的Dex支持。 所以你需要做这些步骤:

  1. Android版的Gradle插件v0.14.0增加了对multi-dex的支持。 要启用,你只需要在build.gradle中声明它:
 android { defaultConfig { ... multiDexEnabled = true } } 
  1. 如果应用程序支持> 5.0(也就是说,如果minSdkVersion为20或更低),则还必须dynamic地修补应用程序ClassLoader,以便能够从二级区域中加载类。 为此你可以添加这个库。
  dependencies { ... compile 'com.android.support:multidex:1.0.0' } 
  1. 在代码中启用你有这些选项。 选一个最适合你的

A.在清单清单中添加MultiDexApplication

 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.android.multidex.App"> <application android:name="android.support.multidex.MultiDexApplication"> </application> </manifest> 

B.通过MultiDexApplication扩展应用程序

 public class App extends MultiDexApplication { .. } 

C.将它安装在应用程序中以附加基础上下文。

 public class App { protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(this); .. } } 

欲了解更多,请通过此链接MultiDex 。