关于Android方法数量限制的问题
限制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
解决方法:
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://developer.android.com/intl/es/tools/building/multidex.html
关于Android方法数量限制的问题的更多相关文章
- Android方法引用超过65535的解决方式
//在app/build.gradle android { compileSdkVersion buildToolsVersion "24.0.1" defaultConfig { ...
- Android方法引用数超过65535优雅解决
随着应用不断迭代更新,业务线的扩展,应用越来越大(比如:集成了各种第三方SDK或者公共开源的Library文件.jar文件)这样一来,项目耦合性就很高,重复作用的类就越来越多了,SO:问题就来了.相信 ...
- 统计apk或jar中方法数量
一.apk中方法数量 ./android-sdk-linux/build-tools/23.0.2/dexdump -f apk路径 | grep method_ids_size 二.jar中方法数 ...
- IDA 调试 Android 方法及简单的脱壳实现
IDA 调试 Android 方法及简单的脱壳实现 标签: android原创逆向调试dalvik 2016-05-24 14:24 9286人阅读 评论(3) 收藏 举报 分类: 原创(25) An ...
- 如何处理 android 方法总数超过 65536 . the number of method references in a .dex file exceed 64k
一:问题描述: 应用中的Dex 文件方法数超过了最大值65536的上限,简单来说,应用爆棚了. 二.解决方案: 方案1:使用插件化框架 比如: https://github.com ...
- 极简Unity调用Android方法
简介 之前写了篇unity和Android交互的教程,由于代码里面有些公司的代码,导致很多网友看不懂,并且确实有点小复杂,这里弄一个极简的版本 步骤 废话不多说,直接来步骤吧 1.创建工程,弄大概像这 ...
- JNI学习2:android 调用C语言方法与C语言调用android方法
#include <jni.h> #include <stdio.h> #include <stdlib.h> #include <jni.h> #in ...
- 使用混淆ProGuard压缩代码和资源/减少方法数量
ProGuard介绍 ProGuard是一个Java类文件压缩器,优化器,混淆器和预先文件验证器. 压缩步骤检测和删除未使用的类,字段,方法和属性. 优化步骤分析和优化方法的字节码. 混淆步骤使用短无 ...
- Unity3D调用android方法(非插件方式)
关于Unity3Dproject与androidproject的转换与合并,请參考我的另外一篇博客.假设你对Unity3Dproject增加到androidproject的过程不熟悉.也请先看完以下这 ...
随机推荐
- IOS开发---菜鸟学习之路--(七)-自定义UITableViewCell
本篇将介绍如何自定义 UITableViewCell 首先选择新建文件 可以直接使用快捷键 COMMAND+n打开新建页面,然后选Objective-C class 然后选择继承之UITableVie ...
- 记一次Entity Framework 项目的优化过程
在博客园看了不少其他大神的经验.今天也抽空贡献点自己的经验(并不是说自己也是大神..小弟还只新手程序员去年才毕业的) 好了废话不多说,直接进入主题.(具体的好坏各位看官就随便看看吧..没有什么好坏之分 ...
- LeetCode118 杨辉三角 Python
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行. 示例:输入: 5 输出: [ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ] cl ...
- maven学习(六)——在别的项目中引用通过Maven安装生成的项目的jar包
1.新建HelloFriend项目,同时建立Maven约定的目录结构和pom.xml文件 HelloFriend | --src | -----main | ----------java | - ...
- 微信小程序--问题汇总及详解之tab切换
设置背景颜色就直接在page里设置 page {background-color: rgb(242, 242, 242);} tab切换: navigator 页面链接 传参的格式为url=&q ...
- java I/O类 File使用
11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...
- unity中的main方法
由于方法命名的原因,无意之间把一个方法命名为了Main,然后把这个方放到了Start方法中去执行,结果运行后发现这个方法竟然执行了两次 情况如下图: -------------- 检查代码,发现脚本并 ...
- 一些filter
Vue.filter('money', (value, symbol = '', currency = '¥', decimals = 0) => { const digitsRE = /(\d ...
- 编译静态库tinyxml2
tinyxml的makefile文件默认是编译可执行的二进制文件xmltest. 需要改成静态库. 更改OUTPUT := xmltest 为:OUTPUT := libtinyxml.a 删除SR ...
- HDU 5322 Hope ——NTT 分治 递推
发现可以推出递推式.(并不会) 然后化简一下,稍有常识的人都能看出这是一个NTT+分治的情况. 然而还有更巧妙的方法,直接化简一下递推就可以了. 太过巧妙,此处不表,建议大家找到那篇博客. 自行抄写 ...