限制Android方法数量的原因是:

Android应用以DEX文件的形式存储字节码文件,在Dalvik字节码规范里,方法引用索引method
referenceindex只有16位,即65536个。

Op & Format

Mnemonic / Syntax

Arguments

6e..72 35c

invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB

B: method reference index (16 bits)

注意是method reference,这里限制的是自己代码、Android框架、第三方库三者方法数量的总和。

dex里方法只能索引65536个,但是报错不在这里。Android打包dex的过程如下:

//Main.Java

-> main() -> run() ->不分包执行runMonoDex()(或者分包执行runMultiDex())->
writeDex()

// DexFile

->toDex() -> toDex0()

//
MethodIdsSection extends MemberIdsSection extends UniformItemSection extends  Section

->Section 的prepare() -> UniformItemSection的prepare0() ->MemberIdsSection的orderItems() -> getTooManyMembersMessage()

//Main.java

->getTooManyIdsErrorMessage()

MemberIdsSection里执行了这么一段代码

protected void orderItems() {

int idx = 0;

if (items().size() >DexFormat.MAX_MEMBER_IDX + 1) {

throw newDexIndexOverflowException(getTooManyMembersMessage());

}

for (Object i : items()) {

((MemberIdItem) i).setIndex(idx);

idx++;

}

}

getTooManyMembersMessage核心代码如下:构建了错误信息字符串。

private String getTooManyMembersMessage() {

try {

String memberType = this instanceofMethodIdsSection ? "method" : "field";

formatter.format("Too many %s references:%d; max is %d.%n" +

Main.getTooManyIdsErrorMessage() + "%n" +

"References bypackage:",

memberType, items().size(),DexFormat.MAX_MEMBER_IDX + 1);

return formatter.toString();

}

}

}

可见代码里检测了方法数量的上限,超过就会报错。这里的限制DexFormat.MAX_MEMBER_IDX

出自

public final classDexFormat {

/**

* Maximum addressable field or methodindex.

* The largest addressable member is0xffff, in the "instruction formats" spec as field@CCCC or

* meth@CCCC.

*/

public static final int MAX_MEMBER_IDX =0xFFFF;

}

因此方法不能超过65536。这里的根源还是在dex字节码规范里方法引用索引的限制,但是强制报错是在这里限制的。

另外,域的数量也有此限制。

错误信息:

Error:Errorconverting bytecode to dex:

Cause:com.android.dex.DexIndexOverflowException:field ID not in [0, 0xffff]: 65536(笔者开发时遇到的是域数量问题,方法数量问题错误信息于此类似)

:XXXXXX:transformClassesWithDexForDebug FAILED

Error:Executionfailed for task ':XXXXXX:transformClassesWithDexForDebug'.

>com.android.build.api.transform.TransformException:com.android.ide.common.process.ProcessException:java.util.concurrent.ExecutionException:com.android.ide.common.process.ProcessException:org.gradle.process.internal.ExecException:
Process 'command 'C:\ProgramFiles\Java\jdk1.8.0_73\bin\java.exe'' finished withnon-zero exit value 2

解决方法:

Google官方出的分包方案,采用MultiDex支持库

1,配置building.gradle,开启MultiDex

android {

defaultConfig {

multiDexEnabled true

}

}

dependencies{

compile'com.android.support:multidex:1.0.0'

}

2,配置应用

方法1:在AndroidManifest.xml的application中声明android.support.multidex.MultiDexApplication;

<?xmlversion="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类继承MultiDexApplication

方法3:让你自己的Application类重写attachBaseContext
方法,

@Override

protected voidattachBaseContext(Context base) {

super.attachBaseContext(base);

MultiDex.install(this);

}

其他错误情况:

Error:java.lang.OutOfMemoryError: Java heap space.

Please assign morememory to Gradle in the project's gradle.properties file.

For example, thefollowing line, in the gradle.properties file, sets the maximum Java heap sizeto 1,024 MB:

<em>org.gradle.jvmargs=-Xmx1024m</em>

:XXXXXX:transformClassesWithDexForDebugFAILED

Error:Executionfailed for task ':XXXXXX:transformClassesWithDexForDebug'.

>com.android.build.api.transform.TransformException:

java.lang.RuntimeException:com.android.ide.common.process.ProcessException:java.util.concurrent.ExecutionException:com.android.ide.common.process.ProcessException:
org.gradle.process.internal.ExecException:Process 'command 'C:\Program
Files\Java\jdk1.8.0_73\bin\java.exe''finished with non-zero exit value 3

解决方法:

Building.gradle里

dexOptions {

javaMaxHeapSize "4g"

}

javaMaxHeapSize对应正则表达式是"\\d+[kKmMgGtT]?"4g指4G字节。

DexOptions类包含了获取JavaMaxHeapSize的方法,对应Building.gradle里dexOptions设置的javaMaxHeapSize。

参考:

http://source.android.com/devices/tech/dalvik/dalvik-bytecode.html

http://jayfeng.com/2016/03/10/%E7%94%B1Android-65K%E6%96%B9%E6%B3%95%E6%95%B0%E9%99%90%E5%88%B6%E5%BC%95%E5%8F%91%E7%9A%84%E6%80%9D%E8%80%83/

http://developer.android.com/intl/es/tools/building/multidex.html

关于Android方法数量限制的问题的更多相关文章

  1. Android方法引用超过65535的解决方式

    //在app/build.gradle android { compileSdkVersion buildToolsVersion "24.0.1" defaultConfig { ...

  2. Android方法引用数超过65535优雅解决

    随着应用不断迭代更新,业务线的扩展,应用越来越大(比如:集成了各种第三方SDK或者公共开源的Library文件.jar文件)这样一来,项目耦合性就很高,重复作用的类就越来越多了,SO:问题就来了.相信 ...

  3. 统计apk或jar中方法数量

    一.apk中方法数量 ./android-sdk-linux/build-tools/23.0.2/dexdump -f  apk路径 | grep method_ids_size 二.jar中方法数 ...

  4. IDA 调试 Android 方法及简单的脱壳实现

    IDA 调试 Android 方法及简单的脱壳实现 标签: android原创逆向调试dalvik 2016-05-24 14:24 9286人阅读 评论(3) 收藏 举报 分类: 原创(25) An ...

  5. 如何处理 android 方法总数超过 65536 . the number of method references in a .dex file exceed 64k

    一:问题描述:     应用中的Dex 文件方法数超过了最大值65536的上限,简单来说,应用爆棚了. 二.解决方案:      方案1:使用插件化框架  比如: https://github.com ...

  6. 极简Unity调用Android方法

    简介 之前写了篇unity和Android交互的教程,由于代码里面有些公司的代码,导致很多网友看不懂,并且确实有点小复杂,这里弄一个极简的版本 步骤 废话不多说,直接来步骤吧 1.创建工程,弄大概像这 ...

  7. JNI学习2:android 调用C语言方法与C语言调用android方法

    #include <jni.h> #include <stdio.h> #include <stdlib.h> #include <jni.h> #in ...

  8. 使用混淆ProGuard压缩代码和资源/减少方法数量

    ProGuard介绍 ProGuard是一个Java类文件压缩器,优化器,混淆器和预先文件验证器. 压缩步骤检测和删除未使用的类,字段,方法和属性. 优化步骤分析和优化方法的字节码. 混淆步骤使用短无 ...

  9. Unity3D调用android方法(非插件方式)

    关于Unity3Dproject与androidproject的转换与合并,请參考我的另外一篇博客.假设你对Unity3Dproject增加到androidproject的过程不熟悉.也请先看完以下这 ...

随机推荐

  1. 设计模式之第15章-适配器模式(Java实现)

    设计模式之第15章-适配器模式(Java实现) “呔,来着何人,报上名来.”“这是谁啊,我怎么没见过”,“就是啊,我也没印象.”“我当然是适配器了,要不然还能是谁.”适配器模式碎碎念:我不就是昨天把你 ...

  2. Mac教程macOS教程 苹果电脑教程

    第1 章 初识MacOS 01 菜单栏 02 键盘 03 聚焦(Spotlight)

  3. Django框架学习-01Django介绍

    01-Django介绍 02-HTTP协议介绍 01-Django介绍 1.什么是Web框架? 随着Web最新发展趋势的不断升级,Web项目开发也越来越难,而且需要花费更多的开发时间.所以,Web程序 ...

  4. Python 拓展之特殊函数(lambda 函数,map 函数,filter 函数,reduce 函数)

    写在之前 今天给大家介绍几个比较特殊的函数,他们具有函数式编程的特点,有人将它们视为 Python 可进行 "函数式编程" 的见证,至于什么是函数式编程,不是本篇文章的重点,感兴趣 ...

  5. SQLAlchemy 学习笔记(三):ORM 中的关系构建

    个人笔记,不保证正确. 关系构建:ForeignKey 与 relationship 关系构建的重点,在于搞清楚这两个函数的用法.ForeignKey 的用法已经在 SQL表达式语言 - 表定义中的约 ...

  6. TOJ 4689: Sawtooth

    4689: Sawtooth Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal Submit: 26     ...

  7. Unity 移动方式总结

    1. 简介 在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position. 2. 通过Transform组件移动物体 Transform 组件用于描述物体在 ...

  8. 管理nuget程序包中搜索不到任何程序包

    之前一直使用vs2012开发,管理nuget程序包没有出现过什么问题.因为开发需要,需要使用vs2015,安装vs2015后再使用vs2012时,发现管理nuget程序包中搜索不到任何资源,晕死. 想 ...

  9. NSByteCountFormatter

    可以将字节转化为我们需要的Kb或者m + (NSString *)stringFromByteCount:(long long)byteCount countStyle:(NSByteCountFor ...

  10. BestCoder 2nd Anniversary/HDU 5719 姿势

    Arrange Accepts: 221 Submissions: 1401 Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 262144/2 ...