As 设置Multidex出现java.lang.NoClassDefFoundError

java.lang.NoClassDefFoundError: org.chiki.base.utils.CommonUtils
at com.***.common.Common$Config.<clinit>(Common.java:32)
at com.***.app.APPContext.initDB(APPContext.java:66)
at com.***.app.APPContext.onCreate(APPContext.java:55)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1024)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4372)
at android.app.ActivityThread.access$1500(ActivityThread.java:135)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5045)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
at dalvik.system.NativeStart.main(Native Method)

一、出现场景
在Android6.0上编译没有问题,而在Android4.+上就出现了这种错误。

二、查找问题
看到这个错误的时候,有点懵了,NoClassDefFoundError(没有发现类错误),上面CommonUtils类是在Lib中的,如果说没有导入库的话,那就有点说不过去了吧。
通过检查build.gradle看到如下这句话:

android {
    ...
    defaultConfig {
        ...
        // 设置MultiDex可用
        multiDexEnabled true
    }
}

对此很好奇这是有什么用的呢?查阅了相关资料,原来是做编译class.dex分包用的。

然后我去解压了apk文件,发现解压出来的文件中包含有两个.dex文件:classes.dex和classes2.dex,再看java.lang.NoClassDefFoundError,结果显而易见,方法数超限了!

而我的项目中正是缺少了下面三步中的其中一步,然后报了错误。

三、解决方式:
这里可以分成四步:

1、 配置完整的build.gradle

android {
	compileSdkVersion 21
    buildToolsVersion "21.1.0"
    // productFlavors是为了避免每次运行都把DEX重新加载一遍而设置的两套运行配置
    productFlavors {
        dev {
            minSdkVersion 21
        }
        prod {
            minSdkVersion 14
        }
    }
    ...
    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
		...
        // 设置MultiDex可用
        multiDexEnabled true
        //MultiDex手动拆包
        //multiDexKeepFile file ('multiDexKeep.txt')
        //multiDexKeepProguard file('multiDexKeep.pro')
    }
    // 保证其他的lib没有被preDex
    dexOptions {
        preDexLibraries = false
    }
}
dependencies {
    ...    
    // MultiDex的依赖
    compile 'com.android.support:multidex:1.0.1'
    ...
}

2、设置AndroidManifest.xml:引入自定义的MyApplication

 <application
        android:name=".MyApplication"
	    ....>
</application>

3、设置MyApplication

public class MyApplication extends MultiDexApplication {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        MultiDex.install(base);
    }
}

4、MultiDex手动拆包:如果上面三步可以了的话,这一步就可以省了。

Android Studio 中提供了相应的手动拆包的方法(可以任选其一),就是第一步中的那两个文件应放置于app->build.gradle同一个目录。
这里写图片描述

  • multiDexKeepFile:手动加入要放到Main.dex中的类。
android/support/multidex/MultiDex.class
  • multiDexKeepProguard:以Proguard的方式手动加入要放到Main.dex中的类。
-keep class android.support.multidex.** {*;}

四、MultiDex的产生背景:
随着时代的发展,现在的应用不断的添加了很多新的功能,酷炫的效果,引入第三方库也成了正常不过的事情,到达一定规模后就可能遇到方法数超限问题。

早期版本错误信息如下:

Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536

较新版本错误信息如下:

trouble writing output:
Too many field references: 131000; max is 65536.
You may try using --multi-dex option.

其中数字65536是关键,Android平台的Java虚拟机Dalvik执行Dex程序时,使用的是short类型来索引DEX文件中的方法。

这就意味着单个Dex文件可被引用的方法总数被限制为64x1024, 即65536。

因此当项目足够大包含方法数目足够多超过了65535(包括引用的外部Lib里面的所有方法),当运行App,就会得到超限错误提示。

为突破这个限制,需要使用multidex来生成多个dex文件,其中也有分主次

Android5.0 (API level 21)之前版本支持Multidex

Android5.0之前使用Dalvik运行时执行应用代码,默认Dalvik限制每个apk只能有一个字节码classed.dex文件。为突破这个限制,可以使用multidex support library来管理额外的dex文件(包括代码)。

Android5.0及更高版本支持Multidex

Android5.0及更高版本使用支持从apk中加载多个dex文件的ART运行时机制,在应用安装时,加载classed(…N).dex文件并编译成一个.oat文件以支持在Android设备上运行。关于Android 5.0运行时详见ART介绍。

Note: While using Instant Run, Android Studio automatically configures your app for multidex when your app’s minSdkVersion is set to 21 or higher. Because Instant Run only works with the debug version of your app, you still need to configure your release build for multidex to avoid the 64K limit.

如果使用Instant Run,当app的minSdkVersion大于或等于21时,Android Studio会自动配置支持multidex,但是仅debug版本有效,release版仍然需要配置multidex来突破64K限制。

看到这里你应该知道我的场景Android6.0可以,然后4.0不行的情况了吧。因为大于5.0自动配置支持了multidex。

借鉴:

更多配置方法数超过 64K 的应用
Android 分Dex (MultiDex)
Android应用使用Multidex突破64K方法数限制

对于出现java.lang.NoClassDefFoundError错误的解决办法,可以尝试以下几个步骤: 1. 检查类路径(Classpath):确保所需的类在项目的类路径中。检查是否已正确设置了依赖项和库文件,并且它们在项目构建路径中。 2. 清理和重建项目:有时编译过程中的错误可能导致类文件丢失或损坏。尝试执行项目的清理操作,然后重新构建项目。 3. 检查依赖项:确认所需的类是否位于正确的依赖项中。如果使用了第三方库或框架,确保已经正确导入并配置了依赖项。 4. 检查类命名和包名:确保类的名称和包名与代码中的引用一致。如果类名或包名有误,会导致无法找到对应的类。 5. 检查Java版本兼容性:如果使用了较新版本的Java特性或API,确保目标设备上的Java版本也支持这些特性。如果目标设备上的Java版本较低,可能会导致NoClassDefFoundError错误。 6. 检查构建工具和环境:如果使用了特定的构建工具(如Gradle或Maven),确保其配置正确并且依赖项已正确添加。还要确保开发环境中使用的编译器和构建工具版本与项目配置兼容。 7. 检查代码逻辑:有时,错误可能是由于代码逻辑错误造成的。检查相关代码,确保类在适当的位置被实例化和引用。 如果以上步骤都没有解决问题,可以进一步查看错误日志和堆栈跟踪,以了解更多关于错误原因的信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值