私有方法会增加 Android 中的 Dex 计数吗?

Do private methods increase Dex Count in Android?

我正在做代码审查,并告诉某人删除一个只使用过一次的私有方法。他们说这无关紧要,因为私有方法引用不会增加 dex 计数。这是真的?我无法通过简单的 google 搜索找到答案。

They said that it didn't matter since dex count wouldn't get increased by private method references. Is this true?

我假设您担心 64K DEX 方法参考限制。在这种情况下,reviewee 是正确的:这段代码是否包装在方法中没有影响。

"the 64K DEX method reference limit"中相关的"method reference"指的是one DEX referring to a method in another DEX。在传统的 Android 项目中,有两个相关的 DEX:您的和框架的。你自己的代码分成多少个方法并不重要。重要的是您引用了多少框架方法("you" 我的意思是您的代码加上您包含的任何库模块和 JAR)。

当您在项目上启用 multidex 时,您会将代码拆分到多个 DEX 文件中。每个都可以引用其他DEX文件中的64K方法。不过,这里 "other DEX files" 指的是框架 DEX 和您自己的应用程序中由 multidex 创建的其他 DEX 文件。但是,据我所知,multidex 不会在 DEX 文件中拆分单个 class。由于这是一个 private 方法,它只能被同一个 class 中的另一个方法引用,所以这两个方法应该在同一个 DEX 文件中。因此,即使在这种情况下,拥有私有方法也不会增加包含该方法的 DEX 的 DEX 方法引用计数。

根据 JesusFreke 的评论,我收回我原来的立场。定义私有方法会增加DEX方法引用计数。

也就是说,在一次性的基础上,担心内联单个方法只是为了减少 DEX 方法引用计数,恕我直言,这是过早的优化。如果您正在接近 DEX 方法引用限制(Android Studio 的 APK 分析器可以帮助您确定这一点),请首先担心库中的 "trimming the fat"。否则,担心可维护性。现在,删除该方法可能实际上对此有所帮助(例如,这是一个两行方法,不值得单独删除)。但是,如果拥有该方法具有可维护性价值,请不要管它。

64k 限制是对 dex 文件中唯一方法引用数量的限制。方法引用由特定的 class 名称、方法名称和方法原型组成,并在您调用方法或 declare/define/override 方法时创建。

所以是的,定义一个新的私有方法将添加一个对 dex 文件的方法引用。


有关详细信息,请参阅:https://source.android.com/devices/tech/dalvik/dex-format.html and https://source.android.com/devices/tech/dalvik/dalvik-bytecode.html,这是 dex 格式的主要参考资料。

"method reference list"是dex文件中method_id_items的排序列表。例如在 dex-format.html 的 "File layout" 部分中查找 "method_ids"。在页面的下方,method_id_item 被定义为由 class 引用、方法名称和方法原型组成。

class_data_item部分用于定义class定义的方法和字段。 "direct_methods" 和 "virtual_methods" 列表是 method_ids 列表中的索引列表 - 这要求 method_ids 列表中存在对该方法的引用。

并且在 dalvik-bytecode.html 中,invoke-* 指令使用方法索引来引用要调用的方法。

有趣的是,方法引用列表本身是用 32 位大小的值定义的(在 dex-format.html 中搜索 "method_ids_size")。因此,方法引用列表本身可能有 4294967296 个条目。

但是,当您需要引用这些方法中的任何一个时,问题就来了。 invoke-* 指令仅使用 16 位来编码方法索引。

此外,class_data项中的方法引用最多可以是完整的32位。因此,理论上您可以在 dex 文件中定义超过 64k 限制的方法,只要您从未真正尝试从该 dex 文件中调用它们。但是它们仍然可以从另一个 dex 文件中调用。