com.android.dex.DexIndexOverflowException

本文介绍了解决Android项目中因方法数量超过65536个限制导致的DexIndexOverflowException问题的三种方法,包括代码优化、使用ProGuard以及启用多dex分包策略。

https://blog.youkuaiyun.com/bright789/article/details/51043825

https://www.cnblogs.com/Sharley/p/7248749.html

当我们在一个项目写的代码越来越多时,在编译项目时就可能出现如下错误(工具不同,版本不同,提示可能有差异):

UNEXPECTEDTOP-LEVEL EXCEPTION:
com.android.dex.DexIndexOverflowException:method ID not in [0, 0xffff]: 65536
         atcom.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:484)
         atcom.android.dx.merge.DexMerger$IdMerger.mergeSorted(DexMerger.java:261)
         atcom.android.dx.merge.DexMerger.mergeMethodIds(DexMerger.java:473)
         atcom.android.dx.merge.DexMerger.mergeDexes(DexMerger.java:161)
         atcom.android.dx.merge.DexMerger.merge(DexMerger.java:188)
         atcom.android.dx.command.dexer.Main.mergeLibraryDexBuffers(Main.java:504)
         atcom.android.dx.command.dexer.Main.runMonoDex(Main.java:334)
         atcom.android.dx.command.dexer.Main.run(Main.java:277)
         atcom.android.dx.command.dexer.Main.main(Main.java:245)
         atcom.android.dx.command.Main.main(Main.java:106)
FAILED
FAILURE:Build failed with an exception.
* Whatwent wrong:
Executionfailed for task ':app:compileDebugJavaWithJavac'.
>Compilation failed; see the compiler error output for details.
* Try:
Run with--stacktrace option to get the stack trace. Run with --info or --debug optionto get more log output

Conversionto Dalvik format failed:
Unableto execute dex: method ID not in [0, 0xffff]: 65536

或者

troublewriting output:

Too manyfield references: 131000; max is 65536.

You maytry using --multi-dex option.


等等这样的错误时,就表明咱们项目中的打包进来的方法过多,超过了最大限制值65536个(这个值在本类错误中每次都出现),这里说的方法包括咱们用到的Android 框架方法,引用的库里的方法以及咱们自己写的方法三类。
 

那么遇到这个问题怎么办法呢?我通过查资源和实践,总结出了三种办法:

1.      咱们自己去看看我们项目中的代码,把没有用到的代码和引用库都去掉,以减少编译时的包含的方法数,这样就不容易达到峰值65536

2.      在编译release版本时加上压缩优化的代码如下:

android {
   ...
    buildTypes {
        release {
            minifyEnabled true
            proguardFilesgetDefaultProguardFile('proguard-android.txt'),
            'proguard-rules.pro'
        }
    }
  }

3.如果做完前两种还是会出现这种问题,那么使用分包的编译方式。

分包的编译方式我也写两个点:

第一个是它的步骤:

第二个是他的缺点及注意事项:

 

分包编译方式的步骤:

1.      在咱们主模块的build.gradle文件的dependencies标签下加入如下代码并编译:

dependencies {
    compile'com.android.support:multidex:1.0.1'
    ...
}


2.      在咱们主模块的build.gradle文件的android标签下的defaultConfig标签下加入multiDexEnabled 项,代码如下:

android {
    compileSdkVersion 21
    buildToolsVersion"21.1.0"
    defaultConfig {
        ...
        minSdkVersion 14
        targetSdkVersion 21
        ...
        multiDexEnabled true
    }
    ...
}


3.      引用MultiDexApplication类,而不Application。

这里边也有三种情况:

1.      咱们没有自定义的Application,所以就在manifest文件中直接加入如下代码:

<?xml version="1.0" encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.android.multidex.myapplication">
    <application
        ...
        android:name="android.support.multidex.MultiDexApplication">
        ...
    </application>
</manifest>


2.      咱们有自己的Application,但是直接继承自Application,那么把Application换成MultiDexApplication即可,样子如下:

    MyApplication extends MultiDexApplication {
.......
}


3.      咱们有自己的Application,但不想换成方法2的办法,那么就在自己Application覆写一个方法如下:

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


好的,已经讲完了分包编译的步骤,其中我出现了几个问题,一并贴出:

问题1:

* Whatwent wrong:

Aproblem occurred configuring project ':app'.

>Could not resolve all dependencies for configuration ':app:_debugCompile'.

   > Could not findcom.android.support:multidex:.

     Searched in the following locations:

        https://jcenter.bintray.com/com/android/support/multidex//multidex-.pom

        https://jcenter.bintray.com/com/android/support/multidex//multidex-.jar

         file:/D:/android/sdk/extras/android/m2repository/com/android/support/multidex//multidex-.pom

         file:/D:/android/sdk/extras/android/m2repository/com/android/support/multidex//multidex-.jar

         file:/D:/android/sdk/extras/google/m2repository/com/android/support/multidex//multidex-.pom

         file:/D:/android/sdk/extras/google/m2repository/com/android/support/multidex//multidex-.jar

     Required by:

         TextMultiDexDemo:app:unspecified

 

* Try:

Run with--stacktrace option to get the stack trace. Run with --info or --debug optionto get more log output.

 

这个主要是我自己没有下载那个包com.android.support:multidex导致的,因为我把步骤1放在了最后,所以出现了这个问题,解决办法就是先添加步骤1并编译成功后,再加步骤2和步骤3

问题2:

Error:Executionfailed for task ':app:dexDebug'. ... Error Code: 3 Output:

UNEXPECTEDTOP-LEVEL ERROR:

java.lang.OutOfMemoryError:GC overhead limit exceeded at com.android.dx.cf.cst.ConstantPoolParser.parse0(ConstantPoolParser.java:326)...

这个是由于我们在编译分包时占用的内存过大,导致出现OOM错误

4.      解决办法:在咱们主模块的build.gradle文件的android标签下的dexOptions标签下加入javaMaxHeapSize "4g"

如下代码:

android {
……
dexOptions {
        javaMaxHeapSize"4g"
    }
…..
}


分包编译的缺点及注意事项:

1.      分包编译出来的包安装到手机上可能会出现无响应的错误,如果分包中的第二包比较大的话,解决办法还是优化自己的代码,减小包的大小

2.       采用分包编译出来的包可适合于 Android4.0 (API level 14) 及以上的版本,如果要支持Android 4.0的版本,可能多测试,因为由于分包后对内存的要求也更大更多,而我们的系统尤其是Android 5.0 (API level 21)之前的版本,为了维护稳定的环境,分配好有限的内存资源,对每个跑起来软件的内存请求限制 ,很有可能会出大问题,甚至出现OOM

3.      如果是编译调试版本,可以使用在build.gradle文件中minSdkVersion 21,这样更快

如果是正式版本,可以使用在build.gradle文件中minSdkVersion14,这样更慢,但支持的用户机型更多
 

 

 

[ 3% 989/30520] Building with Jack: out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/with-local/classes.dex FAILED: /bin/bash -c "(rm -f out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/with-local/classes.dex ) && (rm -f out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jack ) && (rm -rf out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/jack-rsc ) && (mkdir -p out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/with-local/ ) && (mkdir -p out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/ ) && (mkdir -p out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/jack-rsc ) && (rm -f out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/jack-rsc/java-source-list ) && (touch out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/jack-rsc/java-source-list ) && (echo -n 'libcore/dex/src/main/java/com/android/dex/Annotation.java libcore/dex/src/main/java/com/android/dex/ClassData.java libcore/dex/src/main/java/com/android/dex/ClassDef.java libcore/dex/src/main/java/com/android/dex/Code.java libcore/dex/src/main/java/com/android/dex/Dex.java libcore/dex/src/main/java/com/android/dex/DexException.java libcore/dex/src/main/java/com/android/dex/DexFormat.java libcore/dex/src/main/java/com/android/dex/DexIndexOverflowException.java libcore/dex/src/main/java/com/android/dex/EncodedValue.java libcore/dex/src/main/java/com/android/dex/EncodedValueCodec.java libcore/dex/src/main/java/com/android/dex/EncodedValueReader.java libcore/dex/src/main/java/com/android/dex/FieldId.java libcore/dex/src/main/java/com/android/dex/Leb128.java libcore/dex/src/main/java/com/android/dex/MethodId.java libcore/dex/src/main/java/com/android/dex/Mutf8.java libcore/dex/src/main/java/com/android/dex/ProtoId.java libcore/dex/src/main/java/com/android/dex/SizeOf.java libcore/dex/src/main/java/com/android/dex/TableOfConten
07-26
`com.android.art` 是 Android 系统中与 **ART 虚拟机(Android Runtime)** 相关的核心组件,负责应用的执行和优化。以下是详细解析: --- ### **1. 什么是 `com.android.art`?** - **ART (Android Runtime)**:从 Android 5.0(Lollipop)开始取代 Dalvik,作为默认的运行时环境,负责将应用的字节码(DEX)编译为机器码并执行。 - **`com.android.art` 模块**: - 包含 ART 的核心实现(如 JIT/AOT 编译、垃圾回收、线程管理等)。 - 以动态模块(APEX)形式提供,位于 `/apex/com.android.art/`。 - 关键库文件如 `libart.so`(核心运行时库)、`libdexfile.so`(DEX 文件解析)等。 --- ### **2. 在日志中的作用** 在崩溃日志中,`com.android.art` 相关的堆栈通常涉及: - **应用崩溃时的虚拟机状态**(如线程挂起、JNI 调用错误)。 - **性能问题**(如垃圾回收卡顿、JIT 编译耗时)。 - **权限或兼容性异常**(如访问受限的 ART 内部 API)。 例如: ``` native: #00 pc 004f3874 /apex/com.android.art/lib64/libart.so (art::DumpNativeStack+108) ``` 表示崩溃时 ART 正在打印原生调用栈。 --- ### **3. 常见关联问题** #### **问题示例** 1. **JNI 调用失败** - 原因:JNI 代码与 ART 不兼容(如未正确注册本地方法)。 - 日志特征:`art::JNI::CallMethodA` 或 `art::JNI::GetMethodID` 相关错误。 2. **GC 卡顿** - 原因:频繁垃圾回收阻塞主线程。 - 日志特征:`art::gc::Heap::GarbageCollect` 耗时过长。 3. **DEX 加载异常** - 原因:DEX 文件损坏或优化失败。 - 日志特征:`art::DexFile::Open` 或 `art::OatFileManager::OpenDexFilesFromOat` 报错。 --- ### **4. 调试与优化建议** #### **工具** - **Logcat 过滤**: ```bash adb logcat | grep -E "art::|com.android.art" ``` - **Android Profiler**:监控 ART 的 JIT/GC 行为。 - **Systrace**:分析线程阻塞是否与 ART 相关。 #### **代码优化** - **减少 JNI 调用**:批量处理 JNI 操作,避免频繁切换。 - **避免内存泄漏**:使用 `LeakCanary` 检测对象未释放。 - **DEX 优化**:启用 R8/ProGuard 缩减代码,降低 ART 编译负载。 --- ### **5. 关键文件路径** | 文件/目录 | 作用 | |-----------------------------|-------------------------------| | `/apex/com.android.art/lib64/libart.so` | ART 核心运行时库 | | `/data/dalvik-cache/` | AOT 编译后的机器码缓存 | | `/system/framework/arm64/boot.art` | 启动类预编译映像 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值