关于Android方法数量限制的问题

来源:互联网 发布:伴奏升调降调软件 编辑:程序博客网 时间:2024/06/05 00:56

限制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;

原创粉丝点击