Comparando dos archivos .jar

93

¿Cómo comparo dos archivos .jar? Ambos han compilado archivos .class.

Quiero la diferencia en términos de cambios de método, etc.

Kunal
fuente

Respuestas:

95
linuxbuild
fuente
Andrey, ¿cuál es la diferencia entre esas herramientas? ¿Provienen del mismo núcleo?
Nikolay Kuznetsov
3
@NikolayKuznetsov, no, estas herramientas tienen un núcleo diferente. pkgdiff - comparación visual de declaraciones de clases, japi-compliance-checker y clirr - análisis de cambios (el primero está escrito en perl, el segundo - en java).
linuxbuild
¿Ha intentado integrar algo con TeamCity? Parece que clirr tiene un complemento de Maven y también hay una herramienta llamada JAPI-Checker.
Nikolay Kuznetsov
3
Tenga en cuenta que tanto Japi-Compliance-Checker como Pkgdiff no comparan todo. Por ejemplo, se ignoran todas las implementaciones de métodos. Solo se generan como informe las firmas de métodos, las eliminaciones de métodos y las compatibilidades de API. Si desea comparar binarios, puede optar por utilizar herramientas como diff o cmp o el complemento IntelliJ o incluso Beyond Compare.
Sriram
22

Si selecciona dos archivos en IntellijIdea y presiona Ctrl + D, se le mostrará la diferencia. Utilizo Ultimate y no sé si funcionará con la edición Community .

xuesheng
fuente
1
@ChristianNilsson, funciona en 2018.2 en Mac 10.14 Mojave aunque
xuesheng
Cometí el error de seleccionar la envoltura de Maven. En Bibliotecas externas, es necesario expandir el contenedor y luego seleccionar el archivo jar. Gracias @xuesheng
Christian Nilsson
Solución super fácil.
xandermonkey
Increíble, eso es lo que estaba buscando :)
z1lV3r
18
  1. Cambiar el nombre de .jar a .zip
  2. Extraer
  3. Descompilar archivos de clases con jad
  4. recursiva diff
sje397
fuente
2
Es fuerza bruta, pero así es exactamente como lo haría. (Excepto que podría usar jarpara extraer el contenido, en lugar de cambiar el nombre del archivo y usarlo pkunzip).
David R Tribble
2
Opcionalmente, reemplace el paso 3 con una llamada a javap -cpara mantenerlo en código de bytes (especialmente si por "cambios de método" el OP significa cambios en la firma de un método).
Mark Peters
¿Cómo lidiaría con los cuerpos de métodos que se mueven hacia arriba o hacia abajo en el archivo de origen? Creo que eso desequilibraría el diffing javapo la jadsalida.
Marcus Junius Brutus
5

Extraiga cada jar a su propio directorio usando el comando jar con los parámetros xvf. es decir, jar xvf myjar.jarpara cada frasco.

Luego, use el comando UNIX diffpara comparar los dos directorios. Esto mostrará las diferencias en los directorios. Puede usar diff -r dir1 dir2dos recurse y mostrar las diferencias en los archivos de texto en cada directorio (.xml, .properties, etc.).

Esto también mostrará si los archivos de clases binarios difieren. Para comparar realmente los archivos de clase, tendrá que descompilarlos como lo indicaron otros.

Brian
fuente
3

Aquí está mi script para hacer el proceso 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}

Puedo ejecutarlo en Windows usando GIT para Windows. Simplemente abra un símbolo del sistema. Ejecute bash y luego ejecute el script desde allí.

skanga
fuente
2
Parece que se perdió la última línea: diff -r ${EXT_DIR1} ${EXT_DIR2}o ${DIFF} ${EXT_DIR1} ${EXT_DIR2}(si reutiliza su variable declarada). Para aquellos que están en cygwin, el script casi funcionó para mí, excepto dos cosas que cambié: 1) Tuve que usar javap integrado en lugar de jad, porque no puedo descargar jad (enterp. Firewall ... ); 2) como jar xfdoes't entender caminos como la /cygwin/c/rest/of/pathque se devuelve pwden cygwin, tuve que convertirlo a c:/rest/of/path: JAR_DIR=${PWD}, JAR_DIR=${JAR_DIR#*/cygdrive/c},JAR_DIR="c:$JAR_DIR"
PetroCliff
Estás en lo correcto @dpg. La última línea era $ {DIFF} $ {EXT_DIR1} $ {EXT_DIR2}
skanga
¿Qué es jad? No tengo ese binario disponible en PATH
Filip
Jad es un descompilador de Java. Creo que ya no se mantiene, pero lo encontré disponible en javadecompilers.com/jad
skanga
En caso de que sus argumentos (archivos jar) estén en un subdirectorio (como foo/bar/toto.jar), debe agregar el -pargumento al comando mkdir
Duduche
2

En Linux / CygWin, un script útil que utilizo a veces es:

#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
fuente
1

Use Java Decompiler para convertir el archivo jar en un archivo de código fuente y luego use WinMerge para realizar la comparación.

Debe consultar al propietario de los derechos de autor del código fuente para ver si está bien hacerlo.

Cheok Yan Cheng
fuente
1

utilice el decompilador de Java y descompile todos los archivos .class y guarde todos los archivos como estructura de proyecto.

luego use el visor de diferencias de meld y compare como carpetas.

Dulip Chandana
fuente
0

Aquí hay una herramienta aparentemente gratuita http://www.extradata.com/products/jarc/

Tom
fuente
Gracias. Probé este. Produce resultados en XML y se requiere un procesamiento adicional para que sea legible, si tiene muchas clases en .jar
Kunal
1
Para mí, se quejó de que faltaba un tools.jar. Yo uso el JDK, así que ese no es el problema. Creo que no es compatible con java7.
Roel Spilker
@Tom el enlace está roto, esta respuesta podría eliminarse.
David Dossot
0

Intente http://www.osjava.org/jardiff/ - la herramienta es antigua y la lista de dependencias es grande. Según los documentos, parece que vale la pena intentarlo.

Jayan
fuente