MultiDex NoClassDefFound错误

我已经将我的应用程序转换为MultiDex以支持64k的dex限制。 现在看起来像这样:

public class App extends MultiDexApplication { private AppWrapper instance; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); MultiDex.install(base); } @Override public void onCreate() { super.onCreate(); if (instance == null) { instance = new AppWrapper(this); } } } 

我已经将所有通常的逻辑从App应用到AppWidget以使MultiDex能够工作。 而且在其他队友的电脑上也可以。 但是不要和我在一起。 它保持在应用程序创buildjava.lang.NoClassDefFoundError抛出:

 I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;' W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;' W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed E/dalvikvm﹕ Could not find class 'com.playday.app.core.AppWrapper', referenced from method com.playday.app.core.App.onCreate W/dalvikvm﹕ VFY: unable to resolve new-instance 7076 (Lcom/playday/app/core/AppWrapper;) in Lcom/playday/app/core/App; D/dalvikvm﹕ VFY: replacing opcode 0x22 at 0x0007 I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;' W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed D/dalvikvm﹕ DexOpt: unable to opt direct call 0xc21b at 0x09 in Lcom/playday/app/core/App;.onCreate I/MultiDex﹕ VM with version 1.6.0 does not have multidex support I/MultiDex﹕ install I/MultiDex﹕ MultiDexExtractor.load( /data/app/com.playdayteam.playday.debug-1.apk, false) I/MultiDex﹕ Detected that extraction must be performed. I/MultiDex﹕ Trying to delete old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday. debug-2.apk.classes2.dex of size 1484912 I/MultiDex﹕ Deleted old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-2 .apk.classes2.dex I/MultiDex﹕ Trying to delete old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday. debug-2.apk.classes2.zip of size 540964 I/MultiDex﹕ Deleted old file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-2 .apk.classes2.zip D/dalvikvm﹕ GC_CONCURRENT freed 186K, 11% free 3245K/3640K, paused 2ms+4ms, total 28ms D/dalvikvm﹕ WAIT_FOR_CONCURRENT_GC blocked 5ms D/dalvikvm﹕ GC_CONCURRENT freed 156K, 8% free 3593K/3904K, paused 3ms+2ms, total 22ms I/MultiDex﹕ Extraction is needed for file /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam. playday.debug-1.apk.classes2.zip I/MultiDex﹕ Extracting /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-1 .apk.classes576886388.zip I/MultiDex﹕ Renaming to /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-1 .apk.classes2.zip I/MultiDex﹕ Extraction success - length /data/data/com.playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday. debug-1.apk.classes2.zip: 540964 I/MultiDex﹕ load found 1 secondary dex files D/dalvikvm﹕ DexOpt: --- BEGIN 'com. playdayteam.playday.debug-1.apk.classes2.zip' (bootstrap=0) --- D/dalvikvm﹕ DexOpt: --- END 'com. playdayteam.playday.debug-1.apk.classes2.zip' (success) --- D/dalvikvm﹕ DEX prep '/data/data/com .playdayteam.playday.debug/code_cache/secondary-dexes/com.playdayteam.playday.debug-1.apk.classes2. zip': unzip in 28ms, rewrite 387ms I/MultiDex﹕ install done I/MultiDex﹕ install D/AndroidRuntime﹕ Shutting down VM W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41c1d930) E/AndroidRuntime﹕ FATAL EXCEPTION: main java.lang.NoClassDefFoundError: com.playday.app.core.AppWrapper at com.playday.app.core.App.onCreate(App.java:22) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1006) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4457) at android.app.ActivityThread.access$1300(ActivityThread.java:142) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1332) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5105) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method) 

我有相同的Android Studio,gradle,sdk,jdk版本,相同的代码。 我甚至试图格式化硬盘驱动器,并重新安装操作系统,以确保环境是相同的。 什么可能是这个奇怪的问题的原因?

这是我的build.gradle

 apply plugin: 'com.android.application' repositories { maven { url 'http://dl.bintray.com/populov/maven' } mavenCentral() maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } } android { compileSdkVersion project.api_level buildToolsVersion project.build_tools_version defaultConfig { minSdkVersion 14 targetSdkVersion project.api_level } sourceSets { instrumentTest.setRoot('src/test') } packagingOptions { exclude 'META-INF/LICENSE.txt' exclude 'META-INF/LICENSE' exclude 'META-INF/NOTICE.txt' exclude 'META-INF/NOTICE' exclude 'META-INF/ASL2.0' exclude 'AndroidManifest.xml' } defaultConfig { versionName "0.3.2" versionCode 23 } buildTypes { debug { debuggable true applicationIdSuffix ".debug" } beta { debuggable true signingConfig signingConfigs.release applicationIdSuffix ".beta" } release { signingConfig signingConfigs.release runProguard false proguardFile file('proguard-rules.txt') proguardFile getDefaultProguardFile('proguard-android-optimize.txt') } } dexOptions { incremental false preDexLibraries false } } dependencies { compile "com.android.support:support-v13:$project.support_lib_version" compile "com.android.support:support-v4:$project.support_lib_version" compile "com.android.support:appcompat-v7:$project.support_lib_version" compile 'com.google.android.gms:play-services:6.1.11' compile('de.keyboardsurfer.android.widget:crouton:1.8.5@aar') { exclude group: 'com.google.android', module: 'support-v4' } compile('com.octo.android.robospice:robospice:1.4.14'){ exclude group: 'commons-io', module: 'commons-io' } compile('com.octo.android.robospice:robospice-retrofit:1.4.14'){ exclude group: 'commons-io', module: 'commons-io' } compile 'com.squareup.retrofit:retrofit:1.6.1' compile 'com.google.code.gson:gson:2.3' compile 'com.viewpagerindicator:library:2.4.1@aar' compile 'com.squareup.picasso:picasso:2.3.3' compile 'com.squareup.okhttp:okhttp:2.0.0' compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0' compile 'com.etsy.android.grid:library:1.0.5' compile 'com.squareup:otto:1.3.4' compile 'com.darwinsys:hirondelle-date4j:1.5.1' compile 'com.github.chrisbanes.photoview:library:1.2.3' compile 'me.grantland:autofittextview:0.2.0' compile 'it.sephiroth.android.library.horizontallistview:library:1.2.1' compile 'org.ocpsoft.prettytime:prettytime:3.2.4.Final' compile 'com.google.guava:guava:18.0' compile 'com.github.castorflex.smoothprogressbar:library:0.5.2' compile 'com.makeramen:roundedimageview:1.3.0' compile 'org.lucasr.twowayview:twowayview:0.1.1' compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT' compile project(':libs:LoopingViewPager') compile project(':libs:PhotoView-2.2.1') compile files('libs/localytics.jar') compile files('libs/android-support-multidex.jar') compile 'net.hockeyapp.android:HockeySDK:3.0.2' } afterEvaluate { tasks.matching { it.name.startsWith('dex') }.each { dx -> if (dx.additionalParameters == null) { dx.additionalParameters = [] } dx.additionalParameters += '--multi-dex' // enable multidex dx.additionalParameters += "--main-dex-list=$projectDir/multidex.keep".toString() } } 

更新。 我的multidex.keep文件:

 android/support/multidex/BuildConfig.class android/support/multidex/MultiDex$V14.class android/support/multidex/MultiDex$V19.class android/support/multidex/MultiDex$V4.class android/support/multidex/MultiDex.class android/support/multidex/MultiDexApplication.class android/support/multidex/MultiDexExtractor$1.class android/support/multidex/MultiDexExtractor.class android/support/multidex/ZipUtil$CentralDirectory.class android/support/multidex/ZipUtil.class com/playday/app/models/notification/Badge.class com/playday/app/models/User.class com/playday/app/core/AppWrapper.class com/playday/app/core/App.class 

Solutions Collecting From Web of "MultiDex NoClassDefFound错误"

您的AppWrapper类无法加载,因为retrofit.ErrorHandler接口不包含在主dex文件中。

你如何计算哪些类放在你的main-dex-list文件中?
有一个脚本可以为你生成。 我写了一篇博客文章 ,展示了如何使用它。

更新(10/31/2014)
Gradle插件v0.14.0现在自动执行。 在这里看到我的答案。

更新(24/04/2017)
开发者指南解释了如何select具有gradle选项的特定类,如果它没有自动select所有正确的类。

如果您正在扩展MultiDexApplication,则不必进行MultiDex.install(context)调用,因为它已经发生(请参阅源代码链接)。 如果你需要使用attachBaseContext,那么只要确保调用super.attachBaseContext(context)。

https://android.googlesource.com/platform/frameworks/multidex/+/1bb1ab007f6b9405227ea4ce07d2061e4dbb6fe0/library/src/android/support/multidex/MultiDexApplication.java

我们刚刚更新了developers.android.com,并提供了如何使用Android gradle插件支持库的说明,包括开发优化,以便快速开发构build周期。

https://developer.android.com/tools/building/multidex.html

如果有人因为他们的应用程序类在前棒棒糖设备上没有find而在这里,但是应用程序在棒棒糖上运行良好,那么这似乎是Jack和Multidex已知的问题。

参考号: Jack Issue 213484

编号: Jack Issue 224026

NoClassDefFound可以发生在任何没有在Lollipop之前的API上启动multidex的设备上加载的任意类。 如果您正确设置了ProGuard,那么您可以轻松获得,而不必担心MultiDex的开销,从而使您的应用程序在启动发布版本时变得缓慢,特别是在旧设备上。 但是,在debugging模式下开发应用程序时,您不希望ProGuard降低速度。 如果您尝试启用禁用ProGuard的debugging版本,则会开始生成类似com.android.dex.DexIndexOverflowException: Cannot merge new index 72118 into a non-jumbo instruction!构build错误com.android.dex.DexIndexOverflowException: Cannot merge new index 72118 into a non-jumbo instruction!

因此,您真正需要的是启用ProGuard,并且仅在发布版本上禁用multidex,而debugging版本应该与Proguard disabled和multidex启用相反。 当然,你也必须挑剔,使用更less的依赖关系,因为你的发布版本受限于64K。

这需要设置build.gradle以使buildTypesconfiguration,并编译multidex支持库依赖项仅用于debugging。

应用程序子类也必须设置为根据您是否处于multidex模式而从不同的子类派生。 这可以通过使用gradle清单合并原则来实现,方法是为您的debugging版本定义一个覆盖清单,然后以不同的方式指定您的Application类。

这里是相关的应用程序模块build.gradle:

 android { ... buildTypes { debug { minifyEnabled false //Disabled Proguard multiDexEnabled true // Enabling multi-dex support. } release { minifyEnabled true //Enabled Proguard proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' multiDexEnabled false // Disable multi-dex support. } } dependencies { debugCompile 'com.android.support:multidex:1.0.1' //debugCompile makes it included only for debug builds ... } } 

如果您不使用Application子类,那么您只需指定Application子类android.support.multidex.MultiDexApplication的名称,如https://developer.android.com/studio/build/multidex中所述。 HTML但你只想为你的debugging版本做这个。

为此,您必须在debugging变体文件夹层次结构中指定覆盖AndroidManifest.xml,如下所示:

 src - main - AndroidManifest.xml - debug - AndroidManifest.xml 

是的,你在主模块的文件夹旁边创build一个文件夹debug ,然后创build一个AndroidManifest.xml文件,其内容如下所示:

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

这个清单只会被包含在debugging版本中,并且在您的发布版本中将被忽略。

如果你使用了一个Application子类,那么你也可以为你的Application类创build一个独立的基类,它将从不同的父类inheritance,如下所示:

 src - main - AndroidManifest.xml - MyApplication.java (extends from BaseApplication) - BaseApplication.java (extends from Application) - debug - AndroidManifest.xml - BaseApplication.java (extends from MultiDexApplication) 

请注意,我不使用应用程序子类,所以我没有实际尝试这种方法,但它应该工作。

如果一切看起来不错,但是出现这个错误,

尝试禁用即时运行!

当我禁用它时,所有的类都正确加载。

我也有这样的问题。 在我的情况下的解决scheme是:在我的build.gradle文件中,在依赖关系中有多个条目compile 'com.android.support:multidex:1.0.0' 。 喜欢:

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

只是把一个编译'com.android.support:multidex:1.0.0'就像:

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

我终于解决了! 原因不在onCreate()方法中。 logcat的这一行引起了我的注意:

 I/dalvikvm﹕ Failed resolving Lcom/playday/app/core/AppWrapper; interface 8940 'Lretrofit/ErrorHandler;' W/dalvikvm﹕ Link of class 'Lcom/playday/app/core/AppWrapper;' failed 

此行在所有MultiDex日志之前触发。 问题的AppWrapper实现的Retrofit ErrorHandler接口。

正如@AlexLipov在他的回答中所说的,Dalvik找不到ErrorHandler类,并且无法加载AppWrapper

无论如何,解决scheme不是直接通过AppWrapper实现ErrorHandlerAppWrapper将其拉入私有variables。