关于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
解决方法:
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方法数量限制的问题相关推荐
- 《Splunk智能运维实战》——3.6 制作每一主机不同请求方法数量的图表
本节书摘来自华章计算机<Splunk智能运维实战>一书中的第3章,第3.6节,作者 [美]乔史·戴昆(Josh Diakun),保罗R.约翰逊(Paul R. Johnson),德莱克·默 ...
- Android中WebView加载本地Html,与JavaScript与Android方法相互传值...
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010046908/article/details/51759125 最近在做项目中,要使用High ...
- Android中WebView加载本地Html,与JavaScript与Android方法相互传值(续)...
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010046908/article/details/51809558 接着上篇Android中Web ...
- 识别IOS和android方法
识别IOS和android方法 直接上代码,不管是app开发还是手机端web开发都有遇到苹果跟安卓手机兼容性的问题,有时不得不写两套方法,这里根据识别是苹果还是安卓手机后进行设置对应的样式,当然除了用 ...
- js调android方法失败,安卓开发学习之解决JS不能调用Android方法
背景 这两天在做划词搜索时,需要让前端的js调用后端的Android方法,但总是调不成,经过搜索,问题解决,现记录成文. 解决方案 1.确定调用了webView.addJavascriptInterf ...
- Ubuntu共享WiFi(AP)给Android方法汇总
Ubuntu共享WiFi(AP)给Android方法(手工配置) Android不支持Ad-hoc模式的WiFi.Windows 7软AP一个还是比较简单的. 本文介绍在Ubuntu下实现软AP.(需 ...
- ffmpeg移植Android方法以及常见问题汇总
ffmpeg移植Android方法以及常见问题汇总: 1.在ffmpeg官网下载源码包,比如ffmpeg-2.3.在ffmpeg目录下增加Android.mk 和av.mk config.sh三个文件 ...
- CTF-Bugku逆向题Android方法归纳
1.signin题目: reverse() 功能:反转数组里的元素的顺序 语法:arrayobject.reverse.() 这类方法会改变原来的数组,不可逆转 tostring() 功能:将各类进制 ...
- android 计算方法数量,如何精确计算Android应用的使用时长
应用时长的计算友盟早期做法计算每个Activity的时长,然后全部相加就是App的使用时长.后来的做法是在客户端计算,如果应用离开小于30秒内又切回就将切走的时间也算入App的使用时长内. 本人觉得既 ...
最新文章
- linux怎么停止ssh服务,Linux 故障排除:关闭 SSH 会话后如何保存工作状态?
- python爬虫基础教程115_Python解析网页源代码中的115网盘链接实例
- index.html乱码问题,用apache打开文件index显示乱码为什么
- 在 RHEL 和 CentOS 上检查或列出已安装的安全更新的两种方法
- http://kylin.apache.org/development/new_metadata.html
- mysql二进制增量备份
- Java(随笔)——利用HTML,CSS,JavaScript,JQuery编写的简易计算器
- 外部方法调用内部_实战经验:通过类成员函数指针实现类方法调用
- Unity官方支持中文版啦!!!附教程——无需破解!
- 无线ap ntp服务器,我有一优科 ZoneFlex 7982 的无线AP,怎样可以进AP系统进行设置...
- 华为交换机5720常用命令
- 阿里云云计算助理工程师认证(ACA)
- Effie 致创作路上的独行者:动静相宜
- 电脑锁屏卡死以及任务栏卡死的解决办法
- 如何解决merge conflict的方法
- 微型计算机电路软件,微机控制电路
- 手写一个获取验证码的接口,超级简单
- F28335的储存器及其地址分配
- APMServ 5.2.6虚拟主机配置bug
- 2021总结web渗透测试岗位面试题(个人亲身经历的总结)