比较两个.jar文件


93

如何比较两个.jar文件?他们两个都已编译.class文件。

我想要方法更改等方面的差异。

Answers:


95

Andrey,这些工具之间有什么区别?它们是否源自同一核心?
Nikolay Kuznetsov 2014年

3
@NikolayKuznetsov,不,这些工具具有不同的核心。pkgdiff-类声明,japi-compliance-checker和clirr的可视化比较-更改分析(第一个用perl编写,第二个用java写)。
linuxbuild

您是否尝试过将某些东西与TeamCity集成?clirr似乎具有Maven插件,还有一个名为JAPI-Checker的工具。
Nikolay Kuznetsov 2014年

3
请注意,Japi-Compliance-Checker和Pkgdiff都不会比较所有内容。例如,所有方法实现都将被忽略。仅将方法签名,方法删除和API兼容性作为报告生成。如果您打算比较二进制文件,则可以选择使用diff或cmp或IntelliJ插件等工具,甚至可以使用超越比较!
斯里拉姆

22

如果您在IntellijIdea中选择两个文件,然后按Ctrl + D,它将显示差异。我使用Ultimate,但不知道它是否可以与Community Edition一起使用。


1
@ChristianNilsson,虽然可以在Mac 10.14 Mojave上的2018.2中工作
xuesheng

我犯了选择Maven包装器的错误。在“ 外部库”下,需要展开包装器,然后选择jar文件。感谢@xuesheng
Christian Nilsson

超级简单的解决方案。
xandermonkey

令人惊讶的是我一直在寻找:)
z1lV3r

18
  1. 将.jar重命名为.zip
  2. 提取
  3. Jad反编译类文件
  4. 递归差异

2
这是蛮力的,但这正是我要做的方式。(除了我可能jar用来提取内容,而不是重命名文件并使用pkunzip。)
David R Tribble 2010年

2
(可选)将第3步替换为javap -c要保留其字节码的调用(特别是如果通过“方法更改”,OP意味着更改了方法的签名)。
马克·彼得斯2010年

您将如何处理在源文件中上移或下移的方法主体?我认为这将抛出diff的ING javapjad输出不正常的。
Marcus Junius Brutus


5

使用带有参数xvf的jar命令将每个jar提取到它自己的目录中。即jar xvf myjar.jar每个罐子。

然后,使用UNIX命令diff比较两个目录。这将显示目录中的差异。您可以使用diff -r dir1 dir2两个递归并显示每个目录中的文本文件(.xml,.properties等)中的差异。

这还将显示二进制类文件是否不同。要实际比较类文件,您必须按照其他人的说明对它们进行反编译。


3

这是我执行sje397描述的过程的脚本:

    #!/bin/sh

    # Needed if running on Windows
    FIND="/usr/bin/find"
    DIFF="diff -r"

    # Extract the jar (war or ear)
    JAR_FILE1=$1
    JAR_FILE2=$2

    JAR_DIR=${PWD}          # to assign to a variable
    TEMP_DIR=$(mktemp -d)

    echo "Extracting jars in $TEMP_DIR"

    EXT_DIR1="${TEMP_DIR}/${JAR_FILE1%.*}"
    EXT_DIR2="${TEMP_DIR}/${JAR_FILE2%.*}"

    mkdir ${EXT_DIR1}
    cd ${EXT_DIR1}
    jar xf ${JAR_DIR}/${JAR_FILE1}
    jad -d . -o -t2 -safe -space -b -ff -s java -r **/*.class
    cd ..

    mkdir ${EXT_DIR2}
    cd ${EXT_DIR2}
    jar xf ${JAR_DIR}/${JAR_FILE2}
    jad -d . -o -t2 -safe -space -b -ff -s java -r **/*.class
    cd ..

    # remove class files so the diff is clean
    ${FIND} ${TEMP_DIR} -name '*.class' | xargs rm

    # diff recursively 
    ${DIFF} ${EXT_DIR1} ${EXT_DIR2}

我可以使用Windows的GIT在Windows上运行它。只需打开命令提示符。运行bash,然后从那里执行脚本。


2
似乎您错过了最后一行:diff -r ${EXT_DIR1} ${EXT_DIR2}${DIFF} ${EXT_DIR1} ${EXT_DIR2}(如果重复使用声明的变量)。对于那些使用cygwin的人来说,该脚本几乎对我有用,除了我已更改的两件事:1)我不得不使用内置javap而不是jad,因为我无法下载jad(enterp.firewall ... ); 2)作为jar xf简化版,了解路径就像/cygwin/c/rest/of/path是由返回pwdCygwin中,我不得不将其转换为c:/rest/of/pathJAR_DIR=${PWD}JAR_DIR=${JAR_DIR#*/cygdrive/c}JAR_DIR="c:$JAR_DIR"
PetroCliff

您是正确的@dpg。最后一行是$ {DIFF} $ {EXT_DIR1} $ {EXT_DIR2}
skanga

什么jad啊 PATH中没有可用的二进制文件
-Filip

Jad是Java反编译器。我认为它已不再维护,但我在javadecompilers.com/jad上
skanga

如果您的参数(jar文件)位于子目录(如foo/bar/toto.jar)中,则需要将-p参数添加到mkdir命令
Duduche

2

在Linux / CygWin中,我有时使用的便捷脚本是:

#Extract the jar (war or ear)
cd dir1
jar xvf jar-file1
for i in `ls *.class`
do
 javap $i > ${i}.txt #list the functions/variables etc
done

cd dir2
jar xvf jar-file2
for i in `ls *.class`
do
 javap $i > ${i}.txt #list the functions/variables etc
done

diff -r dir1 dir2 #diff recursively




By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.