เปรียบเทียบไฟล์. jar สองไฟล์


95

ฉันจะเปรียบเทียบไฟล์. jar สองไฟล์ได้อย่างไร ทั้งสองได้รวบรวมไฟล์. class

ฉันต้องการความแตกต่างในแง่ของการเปลี่ยนแปลงวิธีการ ฯลฯ

คำตอบ:


98

Andrey อะไรคือความแตกต่างระหว่างเครื่องมือเหล่านี้? พวกเขามาจากแกนเดียวกันหรือไม่?
Nikolay Kuznetsov

3
@NikolayKuznetsov ไม่เครื่องมือเหล่านี้มีแกนหลักที่แตกต่างกัน pkgdiff - การเปรียบเทียบภาพของการประกาศคลาส japi-Compliance-checker และ clirr - การวิเคราะห์การเปลี่ยนแปลง (อันแรกเขียนด้วย perl ที่สอง - ใน java)
linuxbuild

คุณได้ลองผสานรวมบางสิ่งกับ TeamCity แล้วหรือยัง? ดูเหมือนว่า clirr มีปลั๊กอิน Maven และยังมีเครื่องมือที่เรียกว่า JAPI-Checker
Nikolay Kuznetsov

3
โปรดทราบว่าทั้ง Japi-Compliance-Checker และ Pkgdiff ไม่ได้เปรียบเทียบทุกอย่าง ตัวอย่างเช่นการใช้งานวิธีการทั้งหมดจะถูกละเว้น เฉพาะลายเซ็นของเมธอดการลบวิธีการและความเข้ากันได้ของ API เท่านั้นที่สร้างขึ้นเป็นรายงาน หากคุณต้องการเปรียบเทียบไบนารีคุณสามารถเลือกใช้เครื่องมือเช่น diff หรือ cmp หรือปลั๊กอิน IntelliJ หรือแม้แต่ Beyond Compare!
Sriram

25

หากคุณเลือกสองไฟล์ในIntellijIdeaCtrl + Dแล้วกดมันจะแสดงความแตกต่าง ฉันใช้Ultimateและไม่รู้ว่ามันจะใช้ได้กับCommunity edition หรือไม่


1
@ChristianNilsson ทำงานใน 2018.2 บน Mac 10.14 Mojave แม้ว่า
xuesheng

ฉันเลือกกระดาษห่อ Maven ผิดพลาด ภายใต้ไลบรารีภายนอกต้องขยาย wrapper จากนั้นเลือก jar-file ขอบคุณ @xuesheng
Christian Nilsson

ทางออกที่ง่ายสุด ๆ
xandermonkey

น่าอัศจรรย์นั่นคือสิ่งที่ฉันกำลังมองหา :)
z1lV3r

18
  1. เปลี่ยนชื่อ. jar เป็น. zip
  2. สารสกัด
  3. แยกไฟล์คลาสด้วยjad
  4. ความแตกต่างแบบวนซ้ำ

2
มันเป็นพลังที่ดุร้าย แต่นั่นคือวิธีที่ฉันทำ (ยกเว้นว่าฉันอาจใช้jarเพื่อแยกเนื้อหาแทนที่จะเปลี่ยนชื่อไฟล์และใช้pkunzip)
David R Tribble

2
คุณสามารถเลือกที่จะแทนที่ขั้นตอนที่ 3 ด้วยการเรียกjavap -cให้เก็บไว้เป็น bytecode (โดยเฉพาะอย่างยิ่งถ้าโดย "วิธีการเปลี่ยนแปลง" OP หมายถึงการเปลี่ยนแปลงลายเซ็นของวิธีการ)
Mark Peters

คุณจะจัดการกับเมธอดบอดี้ที่ย้ายขึ้นหรือลงซอร์สไฟล์ได้อย่างไร? ฉันคิดว่านั่นจะเป็นการโยนdiffไอเท็มjavapหรือjadเอาท์พุทออกจากการตี
Marcus Junius Brutus


5

แตกแต่ละ jar ไปยังไดเร็กทอรีของตัวเองโดยใช้คำสั่ง jar พร้อมพารามิเตอร์ xvf เช่นjar xvf myjar.jarสำหรับแต่ละโถ

จากนั้นใช้คำสั่ง UNIX diffเพื่อเปรียบเทียบทั้งสองไดเร็กทอรี สิ่งนี้จะแสดงความแตกต่างในไดเรกทอรี คุณสามารถใช้diff -r dir1 dir2recurse สองรายการและแสดงความแตกต่างของไฟล์ข้อความในแต่ละไดเร็กทอรี (.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ที่ถูกส่งกลับโดยpwdใน Cygwin ผมต้องแปลงเป็นc:/rest/of/path: JAR_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 Decompiler ฉันคิดว่ามันไม่ได้รับการดูแลอีกต่อไป แต่ฉันพบว่ามีให้ที่javadecompilers.com/jad
skanga

ในกรณีที่อาร์กิวเมนต์ของคุณ (ไฟล์ jar) อยู่ในไดเร็กทอรีย่อย (เช่นfoo/bar/toto.jar) คุณต้องเพิ่ม-pอาร์กิวเมนต์ในคำสั่ง mkdir
Duduche

2

ใช้Java Decompilerเพื่อเปลี่ยนไฟล์ jar ให้เป็นไฟล์ซอร์สโค้ดจากนั้นใช้WinMergeเพื่อทำการเปรียบเทียบ

คุณควรปรึกษาผู้ถือลิขสิทธิ์ของซอร์สโค้ดเพื่อดูว่าสามารถทำได้หรือไม่


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


0

นี่คือเครื่องมือฟรีที่ชัดเจนhttp://www.extradata.com/products/jarc/


ขอบคุณ. ฉันลองอันนี้แล้ว มันสร้างเอาต์พุตใน XML และต้องมีการประมวลผลเพิ่มเติมเพื่อให้อ่านได้หากคุณมีหลายคลาสใน. jar
Kunal

1
สำหรับฉันมันบ่นเกี่ยวกับ tools.jar ที่หายไป ฉันใช้ JDK ดังนั้นนั่นไม่ใช่ปัญหา ผมว่ามันไม่รองรับ java7
Roel Spilker

@ หากลิงก์เสียคำตอบนี้สามารถลบออกได้
David Dossot

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.