【问题标题】:MultiDex NoClassDefFound errorMultiDex NoClassDefFounderror
【发布时间】:2014-12-26 15:27:47
【问题描述】:

我已将我的应用程序转换为 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 工作。它在其他队友的电脑上运行正常。但不是和我在一起。它在应用程序创建时不断抛出java.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

【问题讨论】:

    标签: java android


    【解决方案1】:

    在gradle中添加下面的依赖

    implementation 'com.android.support:multidex:1.0.3'
    

    在应用级 build.gradle 中,添加如下参数。

     defaultConfig {
         multiDexEnabled = true
     }
    

    在应用程序类中,添加以下行

    MultiDex.install(this);
    

    【讨论】:

      【解决方案2】:

      我尝试了很多没有人为我工作的解决方案。最后,我发现了这个:

          public class MyApplication extends Application {
          @Override
          protected void attachBaseContext(Context base) {
              super.attachBaseContext(base);
              MultiDex.install(this);
          }
      }
      

      这是解决我的问题的唯一方法。也许有人遇到同样的问题,这可能会有所帮助:)

      【讨论】:

        【解决方案3】:

        NoClassDefFound 可能发生在任何未加载到具有早于 Lollipop 的 API 并启用了 multidex 的设备上的任意类中。如果您正确设置了 ProGuard,那么您可以轻松度过难关,而不会因为 MultiDex 开销而导致您的应用在 release 构建时启动缓慢,尤其是在旧设备上。但是,当您在调试模式下开发应用程序时,您不希望 ProGuard 减慢您的速度。如果您尝试在禁用 ProGuard 的情况下启动调试构建,您将开始收到类似 com.android.dex.DexIndexOverflowException: Cannot merge new index 72118 into a non-jumbo instruction!

        的构建错误

        所以您真正想要的是仅在发布版本上启用 ProGuard 和禁用 multidex,而调试版本应该与禁用 Proguard 和启用 multidex 的情况相反。当然,您还必须挑剔并使用更少的依赖项,因为您的发布版本受到 64K 限制。

        这需要将 build.gradle 设置为具有 buildTypes 配置,并编译 multidex 支持库依赖项仅用于调试。

        还必须将 Application 子类设置为从不同的子类派生,具体取决于您是否处于 multidex 模式。这可以使用 gradle 清单合并原则来实现,方法是为您的调试构建定义一个覆盖清单,然后以不同的方式指定您的 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 中所述,但您只想这样做用于您的调试版本。

        为此,您必须在调试和发布变体文件夹层次结构中指定覆盖文件,如下所示:

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

        是的,您在主模块文件夹旁边创建 debugrelease 文件夹。在其中添加以下文件:

        调试/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="com.yourcompany.MyApplication"
                tools:replace="android:name"/>
        </manifest>
        

        此清单将仅包含在调试版本中,并且在您的发布版本中将被忽略。

        release/java/com/yourcompany/BaseApplication.java

        public class BaseApplication extends Application {
        }
        

        debug/java/com/yourcompany/BaseApplication.java

        public class BaseApplication extends MultiDexApplication {
        }            
        

        main/java/com/yourcompany/MyApplication.java

        public class MyApplication extends BaseApplication {
            @Override
            public void onCreate() {
                super.onCreate();
                //Init database, etc. etc.;
            }
        }            
        

        通过这种方式,您可以将应用的功能添加到 MyApplication.java 中,同时具有不同的基类。

        【讨论】:

        • 如果我禁用 multidex 则无法创建 apk
        【解决方案4】:

        如果一切正常,但出现此错误,

        尝试禁用即时运行!!!

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

        【讨论】:

          【解决方案5】:

          我也遇到过这种问题。我的解决方案是: 在我的 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 ........
          }
          

          只放一个 compile 'com.android.support:multidex:1.0.0' like:

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

          【讨论】:

            【解决方案6】:

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

            如何计算要放入 main-dex-list 文件中的类?
            有一个script 可以为您生成它。我写了一个blogpost 来说明如何使用它。

            更新(2014 年 10 月 31 日)
            Gradle 插件 v0.14.0 现在自动完成。看我的回答here

            更新(2017 年 4 月 24 日)
            developer guide 解释了如果不能自动选择所有正确的类,如何使用 gradle 选项选择特定的类。

            【讨论】:

            • 谢谢,我会试试你的脚本。但是 AppWrapper 已经在 main-dex-list 文件中(我将它添加到问题中)。不过,它似乎被忽略了。
            • 您的 AppWrapper 实现了 retrofit.ErrorHandler 接口,该接口也应该放在 main dex 中。 Dalvik 无法解析接口,因此无法加载您的 AppWrapper 类。
            • @AlexLipov 是的,就是这样,我偶然发现了它,但不明白为什么会这样。谢谢解释!
            【解决方案7】:

            如果有人因为在 Lollipop 之前的设备上找不到他们的应用程序类而到达这里,但应用程序在 Lollipop 及更高版本上运行良好,那么这似乎是 Jack 和 Multidex 的一个已知问题。

            参考:Jack Issue 213484

            参考:Jack Issue 224026

            【讨论】:

            • 谢谢!这解决了我的问题。您必须禁用千斤顶编译器,并改用github.com/evant/gradle-retrolambda
            • 您应该解释解决方案,而不仅仅是分享链接。无论如何,谢谢你的链接
            【解决方案8】:

            如果您正在扩展 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 插件一起使用的说明,包括用于快速开发构建周期时间的开发优化。

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

            【讨论】:

            【解决方案9】:

            我终于解决了!原因不在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 日志之前触发。问题的根源在于改造ErrorHandler 接口,AppWrapper 实现了该接口。

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

            无论如何,解决方法是不要直接通过AppWrapper实现ErrorHandler,而是将其拉入私有变量中。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多