安卓ART运行时是否和Dalvik一样有方法限制?

44

Android ART运行时是否像Dalvik一样存在方法数量限制呢? 目前,主dex文件中有64k个方法的限制。

2个回答

75
问题不在Dalvik运行时或DEX文件格式上,而是在当前一组Dalvik指令中。具体来说,是各种方法调用方法,看起来像这样:
invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB

B: method reference index (16 bits)

您可以在DEX文件中引用大量方法,但只能调用前65536个,因为这是方法调用指令中可用的空间。

我想指出的是,限制是在所引用的方法数量上,而不是在定义的方法数量上。如果您的DEX文件只有几个方法,但它们一起调用了70,000个不同的外部定义方法,那么您将超过限制。

修复此问题的一种方法是添加额外的指令以采用更广泛的方法引用。一种称为“jumbo opcodes”的方法已在Android 4.0(ICS)中实现和发布,但从未完全付诸实践,并且后来被从树中删除。(我偶尔会在这里看到帖子,其中包含引用jumbo ops的“dx”错误消息,或者开发人员意外地遇到它们。)

请注意,这不是由Facebook hack解决的问题。这是由于用于存储类/方法/字段元数据的固定大小缓冲区引起的。那里没有特定于方法的限制;您可以通过有很多字段来使缓冲区溢出。
我的理解是,目前的ART实现处理与Dalvik相同的指令集,因此情况不会有所改变。

1
但是如果它们一起调用了70,000个不同的外部定义方法,你将会超出限制。什么样的方法被认为是“外部定义方法”?(Android框架类?还有其他需要注意的吗?)谢谢! - CommonsWare
2
我指的是在单独的DEX文件中定义的方法。对于大多数应用程序,这只是框架和核心库/使用库等内容。顺便说一下,这就是为什么使用multi-dex解决方案(http://android-developers.blogspot.com/2011/07/custom-class-loading-in-dalvik.html)将您的DEX文件分成两个部分,不会让您得到每个DEX文件都恰好有一半方法引用的结果。 - fadden
5
我发现了同样的 dexdeps 工具,并编写了一个更完整的 dex-method-counts 工具,它使用它来输出(按包/类)方法计数:https://github.com/mihaip/dex-method-counts - Mihai Parparita
2
@fadden,您说限制不在于定义的方法数量,但是如果您拿一个空的Android项目并添加一个具有65536个空方法的类,并且不调用其中任何一个,您仍将收到异常。我是否遗漏了什么或者您说错了? - cdroid
2
@cdroid 本地定义的方法无论是否在本地调用,都会被隐式引用。我试图说明,在单个DEX中定义超过64K个方法并不是唯一导致失败的路径。表格中可能存在一些“死空间”。(略微相关:曾经我尝试通过“垃圾回收”索引来减少VM的并行解析实体表的内存占用,但结果并不好,无法证明额外复杂性的价值。请参见https://android.googlesource.com/platform/dalvik/+/froyo/vm/analysis/ReduceConstants.c中的广泛评论。) - fadden
显示剩余3条评论

5

这个Android开发者后台的第11集中,Anwar Ghuloum表示他们不会在不久的将来修复字节码问题。
相反,从Android L开始,他们将通过将所有dex文件(来自APK)折叠成单个oat文件来本地支持多dex。


哦,预L设备将要做什么? - ajma
下一个版本的支持库将覆盖API 4+设备。请在这里查看我的答案:https://dev59.com/wmUp5IYBdhLWcg3wh39W#26196397 - Alex Lipov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接