【问题标题】:Is there a way to get count of number methods used in a jar file有没有办法计算 jar 文件中使用的数字方法
【发布时间】:2012-12-10 23:55:33
【问题描述】:

我可以计算 jar 文件中使用的所有方法的数量吗? 我的 APK 使用了某些外部 JARS,确切地说,有大约 100 个类。

我使用过 dex2jar JAD 等反编译器等等,但它们似乎都只在特定的类文件中显示方法。

有什么办法可以得到总数吗?

【问题讨论】:

  • 您要定义的数字,还是使用的数字?
  • @Peter:我可以根据目的同时使用选项方法声明或方法引用..
  • 所以你说的不是程序运行时实际使用了多少。

标签: java android dex


【解决方案1】:

您可以将jar转换为dex文件,然后从标头中提取方法引用的数量。它存储为无符号小端整数,偏移量为 88 (0x58)。

dx --dex --output=temp.dex orig.jar
cat temp.dex | head -c 92 | tail -c 4 | hexdump -e '1/4 "%d\n"'

请记住,这是引用的唯一方法的数量,而不是方法引用的数量。换句话说,如果某个特定的方法在dex文件中被引用了两次,那么它只会在header中的count中被计入一次。并且当你把这个jar导入你的apk时,两者共有的方法引用会被去重,所以最终合并的apk的总方法引用计数将是

【讨论】:

  • 这是我的答案:android-sdk-macosx/build-tools/17.0.0/dx
  • 谢谢,根据您的回答,我写了一个脚本,用于计算 jar 文件夹中的方法:gist.github.com/toms972/c83504df2da1176a248a
  • 不需要猫/头/尾:hexdump -s 88 -n 4 -e '1/4 "%d\n"' temp.dex
  • 当你组装了一个 dex 文件时,使用 dx 非常好,但是当我超过 65k 限制时我遇到了一种情况,我根本无法组装 dex 文件来检查方法计数。问题仍然存在,如何直接从 jar 中获取方法计数而无需中间 dex
  • @GenaBatsyan 说得好。我的这个答案的目标是提供一个解决方案,使用大多数开发人员可能已经在他们的机器上拥有的工具(至少,在类似 unix 的机器上,安装了 android sdk)。但是,请参阅我刚刚为您描述的案例添加的替代答案,它使用 dx 和 baksmali。
【解决方案2】:

这个 gradle 插件https://github.com/KeepSafe/dexcount-gradle-plugin 将显示组装后的总方法数,并生成包含每个包的方法数的报告。排序后是这样的:

30145    com
27704    org
20950    android
17140    org.spongycastle
16605    android.support
9760     com.google
8930     com.fasterxml.jackson
8930     com.fasterxml
8633     android.support.v4
7020     com.fasterxml.jackson.databind
6426     android.support.v7
5311     com.google.protobuf
4705     org.spongycastle.crypto
...

结合gradle命令

.\gradlew app:dependencies

它会打印出依赖关系树,您将很好地了解哪个依赖关系需要多少方法。

【讨论】:

    【解决方案3】:

    Cyvis 可以读取.jar.class 文件,并且将显示每个方法的总方法数加上圈复杂度和指令数。 GUI 有点......便携......但我已经在 Ubuntu 上运行它,它说它可以在 Windows 上运行。对于有关图书馆给您带来麻烦的可能性的初步信息来源来说,这似乎相当不错。

    【讨论】:

    • 我试过这个工具。如果它对事物进行排序(包按随机顺序),并且您可以递归地查看包及其子包中的类和方法的总数,那将很有用。它没有显示整个项目的全部方法;只是总包和类。
    • 此工具的其他问题:1) 自 2006 年以来未更新。2) 不拆分内部类,仅拆分顶级类。例如,我的外部类有 8 个方法,但内部类可能还有 50 个未提及的方法。
    【解决方案4】:

    使用http://github.com/mihaip/dex-method-counts 计算来自各处的方法数量(JAR、AAR、DEX、APK)

    DEX 或 APK:

    ./dex-method-counts <your_file_path>.DEX 要么 ./dex-method-counts <your_file_path>.APK

    罐子

    只需从 JAR 中创建一个 DEX,如上所示:

    <your_path_to_android_buil_tools>/dx --dex --output=temp.dex orig.jar

    然后

    ./dex-method-counts temp.dex

    AAR

    首先解压它(是的,AAR 实际上是 ZIP),然后使用上面 JAR 部分中显示的 classes.jar

    unzip mylib.aar -d mylib

    dx --dex --output=temp.dex mylib/classes.jar

    dex-method-counts temp.dex

    【讨论】:

      【解决方案5】:

      对于已经超过 64k 方法限制的情况,另一种方法是对 dx 使用 --multi-dex 选项,然后对所有 dx 的 dex 文件使用 baksmali 的“列出方法”功能生成。接下来,您将合并这些列表,对合并的列表进行排序并删除所有重复项。您剩下的方法数将是总方法数。

      dx --dex --multi-dex --output=out orig.jar
      find out -name classes*.dex -exec baksmali list methods {} \; | sort | uniq | wc -l
      

      【讨论】:

      • 注意:“baksmali 列表方法”仅在 baksmali v2.2 中可用
      【解决方案6】:

      如果您有源代码(或可以下载),Sonar 将对其进行这样的静态分析。您还可以检查许多其他复杂性指标,这些指标可能对您尝试做的事情有用。 (可能很高兴告诉我们您要做什么。;))

      【讨论】:

      • 我猜 OP 想知道哪些 JAR 文件值得花时间尝试减少方法计数,以便最终 APK 保持在 64K 限制以下。
      【解决方案7】:
      1. 使用带有-x参数的jar程序extract the files 从你的 jar 文件中。

      2. 对每个 .class 文件应用反编译器以获取方法数 在每个文件中。

      3. 将方法计数加起来。

      【讨论】:

      • 奇怪,我显然对此投了反对票(我不记得这样做了,鼠标点击不好?)。如果您编辑帖子,我可以更改我的投票。对不起:(
      • @powerj1984 没什么大不了的 - 我有很多积分可以用于我的目的。但是我做了一个虚拟编辑,所以你可以整理一下。
      【解决方案8】:

      我只是为此编写了一个 python 脚本来粗略估计

      import re
      import subprocess
      import sys
      
      for jarfile in sys.argv[1:]:
          class_output = subprocess.check_output(['jar', 'tf', jarfile])
          classes = [c.replace('/', '.') for c in re.findall(r'(.*)\.class', class_output)]
          methods = []
          if classes:
              def_out = subprocess.check_output(['javap', '-classpath', jarfile] + classes)
              # This is pretty hacky: look for parentheses in the declaration line.
              num_methods = sum(1 for line in def_out if '(' in line)
          else:
              num_methods = 0
          print '{} {} {}'.format(num_methods, len(classes), jarfile)
      

      我刚刚遇到了 Android 64K 方法限制,我的依赖项还没有被 methodcount.com 服务索引。

      【讨论】:

      • 您可以通过使用 javap 的 -s 标志来避免对括号的破解,并查找以 Signature 开头的行:(
      【解决方案9】:

      我根据@JesusFreke 对这个问题和另一个问题 (https://stackoverflow.com/a/21485222/6643139) 的回答编写了一个脚本:

      #!/bin/bash
      unzip $1 classes.jar -d aarsize &&
        dx --dex --output=aarsize/temp.dex aarsize/classes.jar &&
        hexdump -s 88 -n 4 -e '1/4 "%d\n"' aarsize/temp.dex &&
        rm -rf aarsize
      

      将其保存为文件名“aarsize”,chmod +x 为它,输出为aarsize your_aar_file

      $ aarsize status-bar-compat-release.aar 
      Archive:  status-bar-compat-release.aar
        inflating: aarsize/classes.jar     
      91
      

      91 是您的 aar 文件的方法计数。

      【讨论】:

        【解决方案10】:

        要在 gradle 库中查找方法计数,您可以使用 - http://www.methodscount.com

        它还提供了android studio的插件。

        http://www.methodscount.com/plugins

        【讨论】:

          【解决方案11】:

          使用命令行,在解压 JAR 之后,应该可以这样:

          for f in *.class; do javap -c $(basename -s .class $f) | grep invoke | sed 's/.*Method\(.*\)/\1/g'; done | wc -l
          

          【讨论】:

            【解决方案12】:
            (public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])
            

            使用CTRL+SHIFT+F 在项目中搜索。它帮助了我

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-03-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-05-21
              • 2015-06-06
              • 2020-09-03
              相关资源
              最近更新 更多