【问题标题】:Do private methods increase Dex Count in Android?私有方法会增加 Android 中的 Dex Count 吗?
【发布时间】:2016-11-22 17:41:45
【问题描述】:

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

【问题讨论】:

    标签: android dex


    【解决方案1】:

    64k 限制是对 dex 文件中唯一方法引用的数量的限制。方法引用由特定的类名、方法名和方法原型组成,在您调用方法或声明/定义/覆盖方法时创建。

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


    更多信息参见:https://source.android.com/devices/tech/dalvik/dex-format.htmlhttps://source.android.com/devices/tech/dalvik/dalvik-bytecode.html,它们是dex格式的主要参考。

    “方法引用列表”是dex文件中method_id_items的排序列表。例如在dex-format.html 的“文件布局”部分中查找“method_ids”。在页面下方,method_id_item 被定义为由类引用、方法名称和方法原型组成。

    class_data_item 部分用于定义类定义的方法和字段。 “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 文件中调用。

    【讨论】:

      【解决方案2】:

      他们说这没关系,因为私有方法引用不会增加 dex 计数。这是真的吗?

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

      “64K DEX方法引用限制”中相关的“方法引用”指的是one DEX referring to a method in another DEX。在传统的 Android 项目中,有两个相关的 DEX:你的和框架的。你自己的代码分成多少个方法并不重要。重要的是您引用了多少框架方法(“您”是指您的代码以及您包含的任何库模块和 JAR)。

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

      根据 JesusFreke 的 cmets,我收回了原来的位置。定义私有方法会增加 DEX 方法的引用计数。

      话虽如此,在一次性的基础上,担心内联单个方法只是为了减少 DEX 方法引用计数,恕我直言,这是过早的优化。如果您正在接近 DEX 方法引用限制(Android Studio 的 APK Analyzer 可以帮助您确定这一点),请首先担心库中的“修剪脂肪”。否则,担心可维护性。现在,删除该方法可能实际上对此有所帮助(例如,它是一种两行方法,不值得单独退出)。但是,如果拥有该方法具有可维护性价值,那就别管它了。

      【讨论】:

      • 我了解您要去的部分内容,但我需要更多说明。我在另一篇文章中读到,具有 65536 个空方法的类仍然会达到 dex 限制,dex 对此有何影响?按照这个逻辑,这个类应该在它自己的 dex 文件中,并且没有任何引用。
      • @Tiensi:“我在另一篇文章中读到,具有 65536 个空方法的类仍然会达到 dex 限制”——我不知道是这种情况。不过,事实上,我怀疑具有 64K 方法的类可能无法编译,因为您可能首先会遇到一些编译器限制。 “按照这个逻辑,这个类应该在它自己的 dex 文件中,并且没有任何引用”——正确。
      • @CommonsWare "相关的方法引用......指一个 DEX 引用另一个 DEX 中的方法" 这是不正确的。 intra-dex 和 inter-dex 方法引用之间没有区别。但除此之外,仅在 dex 文件中定义方法(私有或其他方法)这一事实就会将该方法的方法引用添加到 dex 文件中。
      • @JesusFreke:好的。我如何才能使您所说的与 Andy Fadden 在我的答案中链接到的 SO 答案中写的内容相一致?
      • 我认为你误读了他的话。看起来您正在阅读以“我想指出限制在于引用的方法数量,而不是定义的方法数量。”开头的段落。这仅作为一个示例来说明从外部 dex 文件引用的方法包含在方法引用列表中这一事实。 “引用的方法”和“定义的方法”这组并不相互排斥——区别在于从外部 dex 文件引用的方法集。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 1970-01-01
      • 2013-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多