`

Android 分包导致报错ClassNotFoundException

 
阅读更多
http://blog.csdn.net/daitu_liang/article/details/72987378

  昨天中午发现自己现在的项目突然在三星手机上无法启动,一起动就无响应,平时用乐视手机(乐视是新机子6.0,三星是11年的4.4.2),查看日志,折腾了一天时间,还好解决了,最终原因是分包出现问题,项目多次改版,也多半年了,方法数超64K(1K=1024,65536刚好是64K);
我多方面折腾,日志主要出现下图情况:

       主要异常就是  java.lang.NoClassDefFoundError;java.lang.ClassNotFoundException:反正就是类找不到,明明清单里也写配置,项目也没报错,在乐视上还能正常运行,怎么就在三星上出问题了,在第二种异常on path: DexPathList[[zip 涉及到dex,估计和分包可能有关系吧,我把apk解压后,是有classes.dex和classes2.dex,分包成功呢,因为之前的方法数大于64K了,就采用分包,以为这里没问题,然而就坑在这了,分包是成功,但是Android系统在启动应用时加载dex,却并不同时加载这个两个classes.dex和classes2.dex,而是先加载主classes.dex,其他的.dex在应用启动后才进行动态加载安装,如果加载的类不在主dex,就会报错找不到类ClassNotFoundException错误;
解决方案
1、在module下的build.gradle文件 ,添加multiDexEnabled true
defaultConfig {
    applicationId "com.kakaxi.xx"
    minSdkVersion 14
    targetSdkVersion 22
    versionCode 1
    versionName "1.0.1"
    multiDexEnabled true
    testInstrumentationRunner "android.test.InstrumentationTestRunner"

2、在android节点内部添加jumboMode = true
dexOptions {
    javaMaxHeapSize "4g"
    jumboMode = true
}
3、添加分包依赖,谷歌官方推出了multidex兼容包,配合AndroidStudio实现了一个APK包含多个dex的功能
compile 'com.android.support:multidex:1.0.1'
4、让自己的Application继承MultiDexApplication类,或者在Application下重新attachBaseContext(Context base)方法,初始化 MultiDex.install(this);如何下图
@Override
protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(base);
}
选择一种方式即可。

       这样当方法数超过64K时,进行分包,出现类找不到的问题就解决了;
而自己犯的错就是在Application没有处理,也想不起半年前,自己参考哪篇文章,只在gradle里做了配置,application里没做处理,或许当时出现的问题,那个做就OK了,东西还是要理解全面滴,要不不断填坑,不同系统版本的手机在处理多个dex是不一样.项目随意业务增加,改变,加上引用的库增加,方法数很容易超过64k,而单个dex能接纳的方法数不能超过65536个,有这个限制是因为Android会把每个类里的方法统计起来,存在一个short类型为长度的单链表里,short占用两个字节,-2的15次方到2的15次方,即-32768到32768,总保持数量为65536,Android在新的系统5.0里修复了这个问题,但是为了兼容低版本,扔需要处理;
       Android 5.0之前,安卓系统采用的是Dalvik虚拟机,采用的是JIT技术(Just-in-time compilation,即时编译,运行时编译DEX字节码文件,这也是以前为什么安卓手机用户总是诟病Android系统比iOS系统运行卡顿的原因),限制每个APK文件只能包含一个DEX文件(即classes.dex)。为了绕开这个限制,Google给我们提供了multidex support library兼容包,帮助我们实现应用程序加载多个DEX文件,并且这个兼容包作为程序的主DEX文件,管理者其他DEX文件的访问。
       Android 5.0之后,安卓系统改用了ART虚拟机(Android RunTime),采用的是OAT技术(Ahead-of-time,预编译,在应用安装的时候扫描应用中的所有DEX文件,并编译成一个.oat格式的文件供安卓设备执行,所以相比Dalvik虚拟机下的应用,安装时间较长)。因此可以理解为,使用ART虚拟机下的安卓系统自动支持APK文件中多个DEX的加载。所以我用乐视手机(Android 6.0)上apk正常运行,而在三星(Android4.4.2)却无法运行,报找不到类;
       此外,有没有办法指定某些类被分包到主dex呢?有,在app目录下创建一个maindexlist.txt,我们在这个txt里将我们想要放在主dex中的类写进去即可,为了方便减少错误的出现,可以在在\app\build\intermediates\multi-dex\debug目录下找到了一个maindexlist.txt,注意,这个你直接在改了没用,一运行又恢复了,你要的做的是将这个maindexlist.txt复制到app目录下,在进行添加添加指定类即可,

添加指定类后,可以通过对apk进行解压,对主dex进行反编译进行查看,会发现刚才添加的指定类在里面;
分享到:
评论

相关推荐

    Android Caused by: java.lang.ClassNotFoundException解决办法

    "Android Caused by: java.lang.ClassNotFoundException解决办法" 在 Android 开发中,ClassNotFoundException 是一个常见的异常,它通常发生在应用程序启动或运行时。这个异常的出现告诉我们,Java 虚拟机无法找到...

    Hive3.1.2编译源码

    使用hive3.1.2和spark3.0.0配置hive on spark的时候,发现官方下载的hive3.1.2和spark3.0.0不兼容,hive3.1.2对应的版本是spark2.3.0,而spark3.0.0对应的hadoop版本是hadoop2.6或hadoop2.7。 所以,如果想要使用高...

    ClassNotFoundException终极解决办法

    `ClassNotFoundException` 是 Java 开发过程中常见的运行时异常,通常发生在尝试加载某个类时,系统无法在指定的类路径(ClassPath)中找到对应的 `.class` 文件。本文将深入探讨 `ClassNotFoundException` 的原因、...

    java 找不到指定类时发生的异常(ClassNotFoundException)

    如果类文件在编译后没有被放入正确的包结构下,也会导致`ClassNotFoundException`。 4. **资源加载**:如果你使用`ClassLoader`的`loadClass()`方法手动加载类,确保提供了正确的类全名,并且该类加载器能够访问到...

    Struts的java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource异常的解决方法

    然而,对于初学者来说,遇到错误是常有的事,比如“java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource”。这个异常表明在运行时,系统无法找到指定的类,即Apache Commons DBCP的...

    weblogic.xml

    解决AopConfigException类不存在。...Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: org.springframework.aop.framework.AopConfigException 解决方法是把这个文件放到WEB-INF文件夹下面

    java.lang.ClassNotFoundException异常的解决1

    Java中的`ClassNotFoundException`异常通常表示在尝试加载特定类时,JVM无法找到对应的字节码文件。这个异常可能由多种原因引起,但在本场景中,它与Java 9引入的模块系统及其对Java EE API的影响密切相关。 在Java...

    java环境报错大全下载地址

    2. **ClassNotFoundException**:与NoClassDefFoundError类似,但更具体,表示尝试通过`ClassLoader`加载指定的类时未找到。这可能是类路径设置不正确,或者类名输入有误。 3. **NullPointerException**:当尝试...

    Eclipse plugin开发中的ClassNotFoundException问题

    然而,在开发过程中,开发者经常遇到各种问题,其中一种常见的问题是`ClassNotFoundException`。这个异常通常表明Java虚拟机(JVM)在尝试加载一个类时无法找到对应的.class文件。 在标题中提到的"Eclipse plugin...

    http接口调用报错.rar

    接口调用报错:java.net.SocketException: java.lang.ClassNotFoundException: Cannot find the specified class com.ibm.websphere.ssl.protocol.SSLSocketFactory

    JSP中ClassNotFoundException异常的解决办法.pdf

    在Java服务器页面(JSP)开发中,可能会遇到`ClassNotFoundException`异常,这通常是由于系统无法找到或加载指定的类导致的。此异常通常与类路径配置、库引用或JDBC驱动有关。以下是一些解决此类问题的有效方法: ...

    调用百度定位SDK,出现ClassNotFoundException

    在Android应用开发中,使用第三方服务,如百度定位SDK,是一种常见的实践。然而,"ClassNotFoundException"是一个常见的Java运行时异常,通常表示系统无法找到你尝试加载的类。在这个场景下,这个问题可能源于多个...

    Android期末复习题01

    - **执行结果**:这段代码会导致异常,因为直接创建`Toast`对象后不能使用`setText()`方法来设置提示框文本。 **知识点18:`setOnTouchEvent`返回值的区别** - **区别**:返回`true`表示这个消息已经被处理结束,...

    android gson 混淆代码 问题

    6. **运行时异常**:混淆后,可能会遇到`ClassNotFoundException`或`NoSuchFieldException`等异常,这通常是因为混淆破坏了Gson的反序列化过程。通过调试和日志记录定位错误,然后调整混淆规则。 7. **GsonBuilder...

    java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource

    在Java编程中,`java.lang.ClassNotFoundException`是一个常见的运行时异常,它表示JVM尝试加载一个类时,找不到对应的.class文件。在这个特定的错误中,我们看到的是`org.apache.commons.dbcp.BasicDataSource`,这...

    java.lang.ClassNotFoundException: net.sf.ezmorph.MorpherRegistry

    在Java编程中,`ClassNotFoundException` 是一个常见的运行时异常,通常发生在尝试加载特定类时,JVM无法找到对应类的定义。在这个特定的情景中,错误提示 "java.lang.ClassNotFoundException: ...

    解决Android4.0中菜单设置图标无效问题

    } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException e) { Log.w("ReflectionFailed", "Failed to set icon ...

    eclipse 报错java.lang.ClassNotFoundException: com.mysql.jdbc.Driver错误解决

    一:查看你下载的MySQL和mysql-connector-java,如果不对应的话肯定会报错。 对应规则: mysql-connector-java-5 Connector/J version Driver Type JDBC version MySQL Server version Status 5.1 4 3.0, 4.0...

    Android 远程连接mysql 驱动 8.0.29

    } catch (ClassNotFoundException | SQLException e) { e.printStackTrace(); } return conn; } } ``` 在上述代码中,确保替换`your_server_ip`、`port`、`your_database`、`your_username`和`your_password...

Global site tag (gtag.js) - Google Analytics