我可以获得一个JAR文件中使用的所有方法的计数吗? 我的APK使用了某些外部JAR包,确切地说大约有一百个类。
我已经使用过像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文件中多次引用特定方法,则在标题计数中仅计算一次。当您将此jar文件导入apk时,两者共同的方法引用将被去重,因此最终合并的apk的总方法引用计数将<=两个的总和。
hexdump -s 88 -n 4 -e '1/4 "%d\n"' temp.dex
。 - friederbluemle这个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
如果你运行这个程序,它会打印出依赖树。通过查看依赖关系可以很好地了解每个依赖项需要多少方法。
使用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),然后像在JAR部分中展示的那样使用classes.jar
unzip mylib.aar -d mylib
dx --dex --output=temp.dex mylib/classes.jar
dex-method-counts temp.dex
Cyvis 能够读取 .jar
或 .class
文件,并显示每个方法的总方法数、圈复杂度和指令计数。其图形用户界面有些...轻便...但我已在Ubuntu上运行它并且它声称支持Windows。作为第一手信息源,看起来还不错,帮助确认一个库是否会给你带来麻烦。
如果您的方法已经超过了64k的限制,另一种方法是使用--multi-dex选项来运行dx命令,然后在dx生成的所有dex文件上使用baksmali的“列出方法”功能。接下来,您需要合并这些列表,对合并后的列表进行排序并删除任何重复项。剩余的方法数量将是总方法数。
dx --dex --multi-dex --output=out orig.jar
find out -name classes*.dex -exec baksmali list methods {} \; | sort | uniq | wc -l
我刚刚写了一个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服务索引。
使用带有-x参数的jar程序提取您的jar文件中的文件。
对每个.class文件应用反编译器,以获取每个文件中的方法数。
将方法计数相加。
#!/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 文件的方法计数。