zoukankan      html  css  js  c++  java
  • Cannot merge new index 65781 into a non-jumbo instruction! 问题解决(网上摘抄)

    我的报了这个错

    Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
    > com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: Cannot merge new index 65781 into a non-jumbo instruction!

    遭遇MultiDex

    愉快地写着Android代码的总悟君往工程里引入了一个默默无闻的jar然后Run了一下, 经过漫长的等待AndroidStudio构建失败了。
    于是总悟君带着疑惑查看错误信息。

    [java] view plain copy
     
    1. UNEXPECTED TOP-LEVEL EXCEPTION: java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536   
    2.     at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:501)   
    3.     at com.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:276)   
    4.     at com.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:490)   
    5.     at com.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:167)   
    6.     at com.android.dx.merge.DexMerger.merge(DexMerger.java:188)   
    7.     at com.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:439)   
    8.     at com.android.dx.command.dexer.Main.runMonoDex(Main.java:287)   
    9.     at com.android.dx.command.dexer.Main.run(Main.java:230)   
    10.     at com.android.dx.command.dexer.Main.main(Main.java:199)   
    11.     at com.android.dx.command.Main.main(Main.java:103):Derp:dexDerpDebug FAILED  

    看起来是:在试图将 classes和jar塞进一个Dex文件的过程中产生了错误。
    早期的Dex文件保存所有classes的方法个数的范围在0~65535之间。业务一直在增长,总悟君写(copy)的代码越来越长引入的库越来越多,超过这个范围只是时间问题。
    怎么解??太阳底下木有新鲜事,淡定先google一发,找找已经踩过坑的小伙伴。
    StackOverflow 的网友们对该问题表示情绪稳定,谈笑间抛出multiDex。
    这是android官网对当初的短视行为给出的补丁方案。文档说,Dalvik Executable (DEX)文件的总方法数限制在65536以内,其中包括Android framwork method, lib method (后来总悟君发现仅仅是Android 自己的框架的方法就已经占用了1w多),还有你的 code method ,所以请使用MultiDex。 对于5.0以下版本,请使用multidex support library (这个是我们的补丁包!build tools 请升级到21)。而5.0及以上版本,由于ART模式的存在,app第一次安装之后会进行一次预编译(pre-compilation) ,如果这时候发现了classes(..N).dex文件的存在就会将他们最终合成为一个.oat的文件,嗯看起来很厉害的样子。
    同时Google建议review代码的直接或者间接依赖,尽可能减少依赖库,设置proguard参数进一步优化去除无用的代码。嗯,这两个实施起来倒是很简单,但是治标不治本,躲得过初一躲不过十五。 在Google给出这个解决方案之前,他们的开发人员先给了一个简陋简易版本的multiDex具体参看这里。(怀疑后来的官方解决方案就有这家伙参与)。简单地说就是:1.先把你的app 的class 拆分成主次两个dex。2.你的程序运行起来后,自己把第二个dex给load进来。看就这么简单!而且这就是个动态加载模块的框架! 然而总悟君早已看穿Dalvik VM 这种动态加载dex 的能力归根结底还是因为Java 的classloader类加载机制。沿着这条道走,Android模块动态化加载,包括dex级别和apk级别的动态化加载,各种玩法层出不穷。参见这里123456

    第一回合 天真的官方补丁方案

    还是先解决打包问题,回头再研究那些高深的动态化加载技术。偷懒一下咯考虑到投入产出比,决定使用Google官方的multiDex解决。(Google的补丁方案啊,不会再有坑了吧?后面才发现还是太天真) 该方案有两步:
    1.修改gradle脚本来产生多dex。
    2.修改manifest 使用MulitDexApplication。
    步骤1.在gradle脚本里写上:

    [java] view plain copy
     
    1. android {  
    2.     compileSdkVersion 21  
    3.     buildToolsVersion "21.1.0"  
    4.   
    5.     defaultConfig {  
    6.         ...  
    7.         minSdkVersion 14  
    8.         targetSdkVersion 21  
    9.         ...  
    10.   
    11.         // Enabling multidex support.  
    12.         multiDexEnabled true  
    13.     }  
    14.     ...  
    15. }  
    16.   
    17. dependencies {  
    18. compile 'com.android.support:multidex:1.0.0'  
    19. }  

    步骤2.  manifest声明修改

    [java] view plain copy
     
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
    3. package="com.example.android.multidex.myapplication">  
    4. <application  
    5. ...  
    6. android:name="android.support.multidex.MultiDexApplication">  
    7. ...  
    8. </application>  
    9. </manifest>  

    如果有自己的Application,继承MulitDexApplication。如果当前代码已经继承自其它Application没办法修改那也行,就重写 Application的attachBaseContext()这个方法。 

    [java] view plain copy
     
    1. @Override  
    2. protected void attachBaseContext(Context base) {  
    3.     super.attachBaseContext(base);  
    4.     MultiDex.install(this);       
    5.   
    6. }  

    run一下,可以了!但是dex过程好像变慢了。。。
    文档还写明了multiDex support lib 的局限。瞄一下是什么:
    1.在应用安装到手机上的时候dex文件的安装是复杂的(complex)有可能会因为第二个dex文件太大导致ANR。请用proguard优化你的代码。呵呵
    2.使用了mulitDex的App有可能在4.0(api level 14)以前的机器上无法启动,因为Dalvik linearAlloc bug(Issue 22586)  。请多多测试自祈多福。用proguard优化你的代码将减少该bug几率。呵呵
    3.使用了mulitDex的App在runtime期间有可能因为Dalvik linearAlloc limit (Issue 78035)  Crash。该内存分配限制在 4.0版本被增大,但是5.0以下的机器上的Apps依然会存在这个限制。
    4.主dex被dalvik虚拟机执行时候,哪些类必须在主dex文件里面这个问题比较复杂。build tools 可以搞定这个问题。但是如果你代码存在反射和native的调用也不保证100%正确。呵呵

    感觉这就是个坑啊。补丁方案又引入一些问题。但是插件化方案要求对现有代码有比较大的改动,代价太大,而且动态化加载框架意味着维护成本更高,会有更多潜在bug。所以先测试,遇到有问题的版本再解决。

  • 相关阅读:
    应用层协议及ip地址划分
    请求与响应编码及jsp基本原理
    springboot注解
    springboot 快速入门
    Http协议简单解析及web请求过程
    Tomcat原理详解及请求过程
    mysql数据库乱码的问题解决
    AOP的实现原理
    Springl利用Aspectj的扩展实现Aop
    JDK动态代理实现原理
  • 原文地址:https://www.cnblogs.com/woaixingxing/p/7218106.html
Copyright © 2011-2022 走看看