Android工程中方法数超过65536解决方法

一.概况

项目中由于平时使用了不少的三方库,同时随着App的不断迭代自身代码也在不断增加,这时候方法数超过了65536。带来的后果就是编译和打包失败。

二.原因

当方法数超过65536的时候,会报如下的错误。

The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html   
com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536  

65536它代表了引用的总数上限,单个Dex文件(Dalvik可执行文件)中最多可以包含65536个方法;

2.1关于64 k引用限制

Android应用程序(APK)在Dalvik可执行文件的形式包含可执行的字节码文件(DEX)文件,其中包含已编译的代码(运行你的应用程序)。Dex文件最多能包含65536个方法:包括Android框架方法、library方法的总数、和你自己的代码方法总数。因为65536等于64×1024,这一限制被称为“64k引用限制”
这个极限就要求我们配置应用程序的构建过程,需要生成多个DEX文件,所以称为multidex 配置。

2.2不同版本下虚拟机

Android 5.0(API leve 21)之前的系统使用Dalvik虚拟机。默认情况下,Dalvik限制一个apk只有一个Dex文件。为了绕过这个限制,我们可以使用com.android.support:multidex也就是Android官方为我们提供的解决这个问题的一个库,它成为我们APK的主要Dex文件的一部分,负责管理我们APK访问其他Dex文件和代码。(注意: 如果咱的项目minSdkVersion是20或更低,运行到Android 4.4(API leve 20)或者更低版本的设备上时需要禁用AndroidStudio的即时运行)

Android 5.0(API leve 21)和更高的系统使用runtime是ART ,原生支持从应用的apk文件加载多个DEX文件。ART在安装应用时预编译应用程序,会扫描多个classes(..N).dex文件编译成一个.oat的文件。

由于这里只是为了阐明“64 k引用限制”的历史背景,所以关于两种虚拟机的知识点这里不做展开。

三.解决方法

尽量避免64k限制

具体建议:
1.选择三方依赖库的时候做好调研工作,选择满足自己功能的并且尽量小的。(建议能用源码的用源码,对于以后自己的定制和维护很有好处)
2.正式打包构建的时候,使用代码混淆器ProGuard混淆移除未使用的代码,也就是不把没有使用的代码打包到我们的apk中。

解决64k问题

app中build.gradle中添加multiDexEnabled truecompile 'com.android.support:multidex:1.0.1';含义:支持多个dex和依赖multidex库。
apply plugin: 'com.android.application'

android {
    ---省略代码---
    compileSdkVersion 23
    buildToolsVersion '26.0.2'

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 22

        versionCode 61
        versionName "4.2.5"

        // Enabling multidex support.
        multiDexEnabled true
    }

     ---省略代码---
}


dependencies {
    ---省略代码---
    compile 'com.android.support:multidex:1.0.1'
}
继承android.support.multidex.MultiDexApplication类

分两种情况:
第一种有自己的Application
重写Applicatio中这个方法如下

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

第二种没有自己的Application
如果我们的APP没有重写过Application类,我们直接继承MultiDexApplication,然后在manifest.xml中注册Application即可。

与此同时可能会报java.lang.OutOfMemoryError: Java heap space错误,那么解决方法是:在app的build.gradle中android中添加如下代码

    //加大java堆内存大小
    dexOptions {
        javaMaxHeapSize "2g"//这里2g或者4g都可以
    }

四.multidex库的一些限制因素

第二个Dex文件过大问题

1.Dex文件安装到设备的过程非常复杂,如果第二个Dex文件太大,可能导致应用无响应。此时应该使用ProGuard减小Dex文件的大小。

系统低版本问题

1.由于Dalvik linearAlloc的Bug,应用可能无法在Android 4.0之前的版本启动,如果你的应用要支持这些版本就要多执行测试。
2.同样因为Dalvik linearAlloc的限制,如果请求大量内存可能导致崩溃。Dalvik linearAlloc是一个固定大小的缓冲区。在应用的安装过程中,系统会运行一个名为dexopt的程序为该应用在当前机型中运行做准备。dexopt使用LinearAlloc来存储应用的方法信息。Android 2.2和2.3的缓冲区只有5MB,Android 4.x提高到了8MB或16MB。当方法数量过多导致超出缓冲区大小时,会造成dexopt崩溃。
3.Multidex构建工具还不支持指定哪些类必须包含在首个Dex文件中,因此可能会导致某些类库(例如某个类库需要从原生代码访问Java代码)无法使用。
总之就是在做低版本兼容的时候可能会崩溃,要多测试。(不过现在基本面向的用户使用的都是4.4以上的系统,这些情况出现的几率大大降低)。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值