关于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的过程不熟悉.也请先看完以下这 ...
随机推荐
- nsfwjs鉴黄识别最小化案例
3个月前,也就是2月份左右吧,Github上出现一个开源项目: Infinite Red, Inc.工作室宣布开源旗下基于tensorflow的tfjs的鉴黄小工具 据说是从15000张图片中 进行机 ...
- 如何在win7下安装python包工具pip
1. 在安装pip前,请确认你win系统中已经安装好了python,和easy_install工具,如果系统安装成功,easy_install在目录C:\Python27\Scripts 下面, 确认 ...
- CSU-2019 Fleecing the Raffle
CSU-2019 Fleecing the Raffle Description A tremendously exciting raffle is being held, with some tre ...
- Django-缓存机制、跨域请求(CORS)、ContentType组件
Django缓存机制: 在settings中间件里面设置: 三个粒度: 1 全站缓存 用中间件: MIDDLEWARE = [ # 'django.middleware.cache.UpdateCac ...
- AngularJs 特性 之 指令系统
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="utf- ...
- 【bzoj4869】[Shoi2017]相逢是问候 扩展欧拉定理+并查集+树状数组
题目描述 Informatik verbindet dich und mich. 信息将你我连结. B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以分为两种:0 ...
- pat 甲级 1049. Counting Ones (30)
1049. Counting Ones (30) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The tas ...
- Render 使用
Page页面文件,重新Render 方法,目的是把页面的ViewState信息放在最后,利于页面展示速度和SEO优化. Render方法对于重新Html控件还是很好用的. private static ...
- c#中类与结构的区别 struct与class的区别
原文发布时间为:2008-11-23 -- 来源于本人的百度文章 [由搬家工具导入] 类与结构的实例比较 类与结构的差别 如何选择结构还是类 一.类与结构的示例比较: 结构示例: ...
- Syslinux使用
1. 介绍 Syslinux是一个功能强大的引导加载程序, 可以装在U盘上来引导系统 在5.00版本以前,几乎所有c32模块是独立的,即没有其他模块依赖:但在5.00以后,很多c32模块则是依赖于其他 ...