我目前正在尝试从标签重建旧应用程序,不幸的是我得到包含“非二进制等于”.class文件的jar文件。
我试图比较这些.class文件的反编译版本,它们似乎是平等但有一种安全且自动化的方法来诊断这种.class等式吗?
对我来说,知道我生成的jar是否与旧的jar相同是很重要的,即使里面的.class文件不是二进制等于,但在功能上等于(当然是由于不同的javac版本)。
THX
PS。
Major: 52
)javap -c
命令比较“旧”和“新”的输出我没有差异javap -v
命令比较输出,我发现有几行移位(例如:旧的#480在同一指令的新变为#478)和一些缺失的错误声明(例如:{{1}只在旧)答案 0 :(得分:0)
这取决于你所说的“等于”。
如果您指的是字节相等的字节,那么只需使用cmp
实用程序。
你似乎意味着别的东西。但问题在于:“。class”文件中存在足够的可变性,因此准确比较可能很困难:
.class文件的内容取决于所使用的编译器;例如Oracle编译器,Eclipse编译器和其他如Jikes很可能会发出不同的字节代码。
内容取决于编译器选项;例如-source和-target,-g settings等。
.class文件的内容可能取决于精确的编译器主要/次要/补丁版本号。并构建平台。
添加/删除源代码空行或注释等微不足道的更改可能会更改源行号,从而导致不同的.class文件
某些Java编译器将编译器版本和/或时间戳存储为.class文件中的非标准属性。
库中的差异可能会导致针对它们编译的代码的差异。
我建议采用两种方法:
比较javap
输出,忽略不影响常量池中代码,签名和常量的内容
识别用于编译预先存在的JAR的编译器,版本和选项,并在重新编译时使用完全相同的内容。
答案 1 :(得分:0)
我终于找到了一种从我的观点来看可以接受的方法
zipcmp
我写了这个脚本来帮助完成工作
#!/bin/bash
GENERATED="<changeme>/application_5.2.0_generated"
OLD="<changeme>/application_5.2.0_old"
#DECOMPILER="javap -c"
DECOMPILER="java -jar <changeme>/procyon-decompiler-0.5.30.jar"
for plugin in $GENERATED/plugins/*; do
echo "$plugin"
base=$(basename "$plugin")
old_plugin="$OLD/plugins/$base"
zipcmp $plugin $old_plugin
if [ $? -ne 0 ]; then
mkdir -p "$GENERATED/unzip/$base" && cd "$GENERATED/unzip/$base" && jar xf $plugin
mkdir -p "$OLD/unzip/$base" && cd "$OLD/unzip/$base" && jar xf $old_plugin
for class in $(zipcmp $plugin $old_plugin | grep ".class" | awk '{print $4;}' | uniq); do
diff <($DECOMPILER "$GENERATED/unzip/$base/$class") <($DECOMPILER "$OLD/unzip/$base/$class") > /tmp/output
if [ $? -ne 0 ]; then
echo "diff <($DECOMPILER $GENERATED/unzip/$base/$class) <($DECOMPILER $OLD/unzip/$base/$class)"
cat /tmp/output
fi
done
fi
done