Android使用MultiDex发生ClassNotFoundException

背景

在Method与Filed数超限的背景下,我们将多工程拆分成多个Dex打到Apk中解决该问题,但是在使用MultiDex的时候,还会遇到一些问题。 在启动的时候会发生如下Crash。 在4.4以下会Crash,而5.0以上则不会发生Crash

10-11 18:01:26.345 25671-25671/? E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.xxxx.xxxx, PID: 25671
    java.lang.RuntimeException: Unable to instantiate application com.xxxx.xxxx.AApplication: java.lang.ClassNotFoundException: Didn't find class "com.xxxx.xxxx.AApplication" on path: DexPathList[]
        at android.app.LoadedApk.makeApplication(LoadedApk.java:519)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4669)
        at android.app.ActivityThread.access$1500(ActivityThread.java:174)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1458)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:222)
        at android.app.ActivityThread.main(ActivityThread.java:5484)
        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:860)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:676)
        at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "com.xxxx.xxxx.AApplication" on path: DexPathList[]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:497)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:457)
        at android.app.Instrumentation.newApplication(Instrumentation.java:975)
        at android.app.LoadedApk.makeApplication(LoadedApk.java:514)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4669) 
        at android.app.ActivityThread.access$1500(ActivityThread.java:174) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1458) 
        at android.os.Handler.dispatchMessage(Handler.java:110) 
        at android.os.Looper.loop(Looper.java:222) 
        at android.app.ActivityThread.main(ActivityThread.java:5484) 
        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:860) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:676) 
        at dalvik.system.NativeStart.main(Native Method) 

原因

由于Project的Application继承关系,父类与子类不在同一个Dex中,导致在加载的时候会Crash。因为5.0以下的手机使用的是Dalvik虚拟机,在Dex加载的时候,通过JIT即时编译生成字节码然后运行,而Art虚拟机则是在安装的时候,已经将Dex转换成aot文件,而aot文件已经是可以执行的二进制文件,所以在安装的时候,5.0以上的手机会安装比较久,但是执行的速度会比5.0以下的手机快。

所以,在5.0以下的手机中,Dalvik会优先加载第一个Dex,然后反射到Application然后进行初始化,如果子类不在第一个Dex中,那么就会出现ClassNotFoundException的异常。而5.0以上的手机,在安装的时候就编译完成了,所以直接加载了字节码文件则不会出现该问题。

举例

例如,一个Project的Application为MainApplication,该类存在于A工程中。而该类继承自SubApplication,该类存在于B工程中。而A工程,在classes.dex,B工程在classes2.dex中。而在打完包出来后,在4.x的手机中会出现该异常。

参考资料

配置方法数超过 64K 的应用

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JadePeng的技术博客

Netty断线重连

Netty断线重连 最近使用Netty开发一个中转服务,需要一直保持与Server端的连接,网络中断后需要可以自动重连,查询官网资料,实现方案很简单,核心思想是...

4505
来自专栏一个会写诗的程序员的博客

第16章 Spring Boot + Kotlin: 下一代 Java 服务端开发

2017-11-22 11:55:17.205 INFO 14721 --- [ main] org.hibernate.Version ...

1531
来自专栏Java与Android技术栈

使用 Kotlin + Spring Boot 进行后端开发Kotlin示例一:结合 Redis 进行数据存储和查询示例二:结合 RxJava 模拟顺序、并发地执行任务总结

Kotlin 是一个基于 JVM 的编程语言,它的简洁、便利早已不言而喻。Kotlin 能够胜任 Java 做的所有事。目前,我们公司 C 端 的 Androi...

1283
来自专栏java、Spring、技术分享

Spring Import 三种用法与源码解读

  最近在看Spring Cloud相关的源码,每次引入一个新的starter,发现都会加一些enable的注解,比如:@EnableDiscoveryClie...

2284
来自专栏技术小黑屋

Android中一个简单有用的发现性能问题的方法

在Android中,性能优化是我们持之不懈的工作。这其中,在主线程执行耗时的任务,可能会导致界面卡顿,甚至是ANR(程序未响应)。当然Android提供了很多优...

931
来自专栏张善友的专栏

MSBUILD 命令行编译的时候请注意msbuild文件名称或路经中空格导致出错

在使用MSBUILD 去编译msbuild文件的时候,如果这个方案或者项目的名称或者路经中间有空格符号,需要把这个方案或者项目整个用引号引起来,否则编译的时候会...

2075
来自专栏石奈子的Java之路

原 荐 SpringBoot 2.0 系列0

3813
来自专栏一个会写诗的程序员的博客

《Springboot极简教程》 第11章 Springboot集成mongodb开发小结

本章我们通过SpringBoot集成mongodb,Java,Kotlin开发一个极简社区文章博客系统。

984
来自专栏后端之路

基于SpringBoot的CodeGenerator

背景 目前组织上对于一个基础的crud的框架需求较多 因此选择了SpringBoot作为基础选型。 Spring Boot是由Pivotal团队提供的全新框架,...

1.9K11
来自专栏java闲聊

SpringBoot Cache 入门

@CacheEvict(cacheNames = "tea",key = "#id")

2065

扫码关注云+社区