Comparando dois arquivos .jar

93

Como posso comparar dois arquivos .jar? Ambos compilaram arquivos .class.

Eu quero a diferença em termos de mudanças de método, etc.

Kunal
fonte

Respostas:

96
linuxbuild
fonte
Andrey, qual é a diferença entre essas ferramentas? Eles vêm do mesmo núcleo?
Nikolay Kuznetsov
3
@NikolayKuznetsov, não, essas ferramentas têm núcleos diferentes. pkgdiff - comparação visual de declarações de classes, japi-compliance-checker e clirr - análise de mudanças (o primeiro é escrito em perl, o segundo - em java).
linuxbuild
Você já tentou integrar algo com TeamCity? Parece que o clirr tem um plug-in Maven e também uma ferramenta chamada JAPI-Checker.
Nikolay Kuznetsov
3
Observe que o Japi-Compliance-Checker e o Pkgdiff não comparam tudo. Por exemplo, todas as implementações de método são ignoradas. Apenas assinaturas de método, remoções de método e compatibilidades de API são geradas como um relatório. Se você quiser comparar binários, pode optar por usar ferramentas como diff ou cmp ou plugin IntelliJ ou mesmo Beyond Compare!
Sriram
22

Se você selecionar dois arquivos em IntellijIdea e pressionar Ctrl + D, será mostrado o diff. Eu uso o Ultimate e não sei se vai funcionar com a edição Community .

xuesheng
fonte
1
@ChristianNilsson, funciona em 2018.2 no Mac 10.14 Mojave
xuesheng
Cometi o erro de selecionar a embalagem do Maven. Em Bibliotecas externas, é necessário expandir o invólucro e, em seguida, selecionar o arquivo jar. Obrigado @xuesheng
Christian Nilsson
Solução super fácil.
xandermonkey
Incrível é isso que eu estava procurando :)
z1lV3r
18
  1. Renomear .jar para .zip
  2. Extrair
  3. Descompilar arquivos de classe com jad
  4. Diferença recursiva
sje397
fonte
2
É força bruta, mas é exatamente assim que eu faria. (Exceto que posso usar jarpara extrair o conteúdo, em vez de renomear o arquivo e usá-lo pkunzip.)
David R Tribble,
2
Opcionalmente, substitua a etapa 3 por uma chamada para javap -cpara mantê-lo em bytecode (especialmente se por "alterações de método" o OP significa alterações na assinatura de um método).
Mark Peters,
Como você lidaria com corpos de método sendo movidos para cima ou para baixo no arquivo de origem? Eu acho que seria jogar o diffing de javapou jadsaída fora de sintonia.
Marcus Junius Brutus
5

Eu uso para ZipDiff lib (tem Java e API Ant).

FoxyBOA
fonte
5

Extraia cada jar para seu próprio diretório usando o comando jar com os parâmetros xvf. ou seja, jar xvf myjar.jarpara cada frasco.

Em seguida, use o comando UNIX diffpara comparar os dois diretórios. Isso mostrará as diferenças nos diretórios. Você pode usar diff -r dir1 dir2dois recurse e mostrar as diferenças nos arquivos de texto em cada diretório (.xml, .properties, etc).

Isso também mostrará se os arquivos de classe binários são diferentes. Para realmente comparar os arquivos de classe, você terá que descompilá-los conforme observado por outros.

Brian
fonte
3

Aqui está meu script para fazer o processo descrito por 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}

Posso executá-lo no Windows usando o GIT para Windows. Basta abrir um prompt de comando. Execute o bash e execute o script a partir daí.

skanga
fonte
2
Parece que você perdeu a última linha: diff -r ${EXT_DIR1} ${EXT_DIR2}ou ${DIFF} ${EXT_DIR1} ${EXT_DIR2}(se reutilizar sua variável declarada). Para quem está no cygwin, o script quase funcionou para mim, exceto duas coisas que mudei: 1) Tive que usar o javap integrado em vez do jad, porque não consigo baixar o jad (enterp. Firewall ... ); 2) como jar xfdoes't entender caminhos como /cygwin/c/rest/of/patho que é retornado por pwdno cygwin, eu tive que convertê-lo em c:/rest/of/path: JAR_DIR=${PWD}, JAR_DIR=${JAR_DIR#*/cygdrive/c},JAR_DIR="c:$JAR_DIR"
PetroCliff
Você está correto @dpg. A última linha foi $ {DIFF} $ {EXT_DIR1} $ {EXT_DIR2}
skanga
O que é jad? Não tem esse binário disponível no PATH
Filip
Jad é um descompilador Java. Acho que não é mais mantido, mas encontrei-o disponível em javadecompilers.com/jad
skanga
Caso seus argumentos (arquivos jar) estejam em um subdiretório (como foo/bar/toto.jar), você precisa adicionar o -pargumento ao comando mkdir
Duduche
2

No Linux / CygWin, um script útil que uso às vezes é:

#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
SidJ
fonte
1

Use o Java Decompiler para transformar o arquivo jar em arquivo de código-fonte e, a seguir, use o WinMerge para realizar a comparação.

Você deve consultar o detentor dos direitos autorais do código-fonte, para ver se está correto fazer isso.

Cheok Yan Cheng
fonte
1

use o descompilador java e descompile todos os arquivos .class e salve todos os arquivos como a estrutura do projeto.

em seguida, use o meld diff viewer e compare como pastas.

Dulip Chandana
fonte
0

Aqui está uma ferramenta aparentemente gratuita http://www.extradata.com/products/jarc/

Tom
fonte
Obrigado. Eu tentei este. Ele produz saída em XML e processamento adicional é necessário para torná-lo legível, se você tiver muitas classes em .jar
Kunal,
1
Para mim, ele reclamou da falta de um tools.jar. Eu uso o JDK, então esse não é o problema. Acho que não suporta java7.
Roel Spilker
@Tom o link está quebrado, esta resposta pode ser removida.
David Dossot