Android 上为啥会有65536的限制,解释下原因

8,992 阅读2分钟

该文章已经收集到面试题整理(可在首页点击底部 Tab 看到)。

在这之前的一篇文章中,我们模拟了关于65536问题的面试场景 关于 65536 限制与 MultiDex 会在面试中被问到的问题可能都在这了

然后归纳出了面试中可能会出现的问题:

  • Android 上为啥会有65536的限制,解释下原因。

  • Android 官方是如何解决65536问题的?MultiDex 在打包阶段和 app 运行阶段分别做了什么?

  • 使用 MultiDex 可能会造成什么问题?

  • 使用 MultiDex 后首次启动 app 有什么优化方向吗?

  • 如何将指定的 class 打进 mainDex ?

那么这篇开始回答第一个问题:Android 上为啥会有65536的限制,解释下原因。

日常开发中,工程中有大量方法是很常见的,但当方法数超过65536时,编译时会出现这个错误:

一个 dex 文件的方法引用数不能大于 64k,64k 的准确值是(64 * 1024 = 65536)。

65536 这个值是咋来的呢?我们依然从源码入手:

全局搜索 ; max is ,发现 MemberIdsSection#getTooManyMembersMessage 使用了:

再看看 getTooManyMembersMessage 被谁调用的?

MAX_MEMBER_IDX 的值是多少?

那么 65536 这个值是咋来的,我们很清楚了,而且从源码中我们还得知除了方法数有限制之外,成员变量的个数也被限制了。

但是,这还不是面试官想要的答案,源码中的 MAX_MEMBER_IDX 为什么要定义成 0xFFFF 呢?

这个我在 stackoverflow 上找到了答案:

invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB 是啥?来看看关于 davilk 指令的官方文档:

解释一下:

invoke-kind (调用各类方法)指令中,方法引用索引数是 16 位的,也就是最多调用 2^16 = 65536 个方法,这就是 DexFormat 中 MAX_MEMBER_IDX 为 0xFFFF 的原因。

说个题外话,在看这个 davilk 指令的时候 ,我注看到了 vC..vG 这几个参数寄存器,心中就产生了一个疑问,Java 方法里的参数个数上限是多少呢?感兴趣的可以试试。

关于 Android 上为啥会有65536的限制的解释就是以上了,希望对大家有帮助。