我可以计算 jar 文件中使用的所有方法的数量吗?我的 APK 使用某些外部 JARS,确切地说,有大约数百个类。
我使用过 dex2jar JAD 等反编译器等等,但它们似乎都只在特定的类文件中显示方法。
有没有办法可以得到总数?
您可以将 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的总方法引用计数将是<=两者之和。
这个 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
它打印出依赖关系树,您将很好地了解哪个依赖关系需要多少方法。
Cyvis可以读取一个.jar
或.class
文件,并将显示每个方法的总方法数加上圈复杂度和指令数。GUI 有点......便携......但我已经在 Ubuntu 上运行它,它说它可以在 Windows 上运行。对于有关图书馆给您带来麻烦的可能性的初步信息来源来说,这似乎相当不错。
使用http://github.com/mihaip/dex-method-counts计算来自各处的方法数(JAR、AAR、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 它实际上是 ZIP)然后使用 classes.jar 如上面 JAR 部分所示
unzip mylib.aar -d mylib
dx --dex --output=temp.dex mylib/classes.jar
dex-method-counts temp.dex
对于已经超过 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
如果你有源代码(或者可以下载),Sonar会在上面做这样的静态分析。您还可以检查许多其他复杂性指标,这些指标可能对您尝试做的事情有用。(可能很高兴告诉我们您要做什么。;))
使用带有 -x 参数的 jar 程序 从 jar 文件中提取文件。
对每个 .class 文件应用反编译器以获取每个文件中的方法数。
将方法计数相加。
我只是为此编写了一个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 服务索引。
我根据@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 文件的方法计数。
要在 gradle 库中查找方法计数,您可以使用它 - http://www.methodscount.com
它还为 android studio 提供插件。
使用命令行,在解压缩 JAR 后,应该可以这样:
for f in *.class; do javap -c $(basename -s .class $f) | grep invoke | sed 's/.*Method\(.*\)/\1/g'; done | wc -l
(public|protected|private|static|\s) +[\w\<\>\[\]]+\s+(\w+) *\([^\)]*\) *(\{?|[^;])
使用在项目中搜索CTRL+SHIFT+F
。它帮助了我