How do I compare two .jar files?
Both of them have compiled .class files.
I want the difference in terms of method changes, etc.
JAPICC, sample usage:
japi-compliance-checker OLD.jar NEW.jar
Sample reports for log4j: http://abi-laboratory.pro/java/tracker/timeline/log4j/
PkgDiff, sample usage:
pkgdiff OLD.jar NEW.jar
See sample report for args4j.
Clirr, sample usage:
java -jar clirr-core-0.6-uber.jar -o OLD.jar -n NEW.jar
If you select two files in IntellijIdea and press Ctrl + Dthen it will show you the diff. I use Ultimate and don't know if it will work with Community edition.
Rename .jar to .zip
Extract
Decompile class files with jad
Recursive diff
Extract each jar to it's own directory using the jar command with parameters xvf. i.e. jar xvf myjar.jar for each jar.
Then, use the UNIX command diff to compare the two directories. This will show the differences in the directories. You can use diff -r dir1 dir2 two recurse and show the differences in text files in each directory(.xml, .properties, etc).
This will also show if binary class files differ. To actually compare the class files you will have to decompile them as noted by others.
Create a folder and create another 2 folders inside it like old and new. add relevant jar files to the folders. then open the first folder using IntelliJ. after that click whatever 2 files do you want to compare and right-click and click compare archives.
I use to ZipDiff lib (have both Java and ant API).
Here is my script to do the process described by 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}
I can run it on Windows using GIT for Windows. Just open a command prompt. Run bash and then execute the script from there.
Use Java Decompiler to turn the jar file into source code file, and then use WinMerge to perform comparison.
You should consult the copyright holder of the source code, to see whether it is OK to do so.
In Linux/CygWin a handy script I use at times is:
#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
If you are using IntelliJ IDEA or Android Studio, add your jar files to a project under the libs folder.
Then select the both jar files, right click then select "Compare Archives"
use java decompiler and decompile all the .class files and save all files as project structure .
then use meld diff viewer and compare as folders ..
Here's an aparently free tool http://www.extradata.com/products/jarc/
Please try http://www.osjava.org/jardiff/ - tool is old and the dependency list is large. From the docs, it looks like worth trying.
This application may be what you need, works great and display a simple GUI showing differences. Try Jarcomp
Related
I'm trying to get an updated path of my variable service_SOURCES, after I have generated some files from jaxb with my makefile:
service.jar$(EXEEXT): $(service_SOURCES)
mkdir -p bin
xjc -d src -p gen.files ./src/resources/info.xsd
javac -cp service_SOURCES
service_SOURCES := $(shell find ./src -name "*.java")
I am trying to compile my existing java code with my generated java code Currently, my service_SOURCES variable finds my folder containing my java files, and compiles them all together. I need it to update to include the newly generated java folder, so it compiles my new java files along with my old java files.
I've tried linking the above commands together using && but the shell command still doesn't update. If I run the above commands in terminal it works, but when I run it in my Makefile the path won't update properly.
(moving to answer as this doesn't fit in comment)
You should understand that Make runs in two phases -- The dependency tree is built in the first phase, and the rules are run in the second. This means that the dependency tree cannot be updated by a shell command run after files are generated by a recipe. If you want to do something like this (and I agree with #JohnBollinger, this might not be the best idea), you might need to split your logic between two makefiles, or have a self-recursive makefile. Either way you need to generate the files, then call the second makefile, which can then build a new dependency tree based on a timely shell command.
Alternative:
service.jar$(EXEEXT): _target_to_generate_java_files_
mkdir -p bin
xjc -d src -p gen.files ./src/resources/info.xsd
javac -cp $$(find ./src -name "*.java")
I've used an older version of Google's Java to Objective-C (J2ObjC) converter previously (i.e. version 0.5.2) and it was straightforward to translate an entire folder of Java files to their equivalent Objective-C files (and to preserve the directory structure in doing so). I just had to run the following shell executable:
$ ./run.sh —-preservedirs <path to input folder>
I've just downloaded the latest version of J2ObjC (i.e. version 0.9.1) and it's not clear from the Getting Started page or elsewhere how I can translate an entire folder of Java files rather than just a single Java file using the j2obc executable. The only example provided in the Getting Started page is to translate a single Java file which has no dependencies or imports elsewhere as follows:
$ ./j2objc Hello.java
Can anyone provide me with an example of how to translate an entire package assuming I have a folder named input which contains my com package which contains all of the sub-packages and Java files that I want to translate?
To build a whole project, I add the source root(s) to the -sourcepath, then use the find command to locate all Java sources. For example, to build Square.com's Dagger library:
$ export J2OBJC=~/j2objc # change to wherever your distribution is
$ cd ~/src/dagger/core
$ $J2OBJC/j2objc -d build_output -sourcepath src/main/java \
-classpath $J2OBJC/lib/javax-inject.jar \
`find src/main/java -name '*.java'`
All the generated .h and .m files are now in the build_output directory, in subdirectories according to their package (like javac does). To compile all the .m files into a static library, I use:
$ cd build_output
$ j2objcc -c -I. `find . -name '*.m'`
$ libtool -static -o libdagger.a *.o
If there is no better way built into run.sh, you could use find's -exec flag:
find <path to input folder> -type f -exec --preservedirs ./run.sh {} \;
Or, you could use xargs to do multiple files at the same type:
find <path to input folder> -type f | xargs ./run.sh --preservedirs
(You might also need to add -name "*.java" to the find arguments if there are non-Java files in your directories).
I need to make a makefile for a Java project.
My project is basic. A package which contains my main file and some others packages.
Can someone help me to make a proper makefile for that kind of project ?
Sorry I have not tested so it is likely to fail...
Assuming that what you need is to generate a executable jar file the following should work but I have not tested it.
The Makefile below assumes that your sources are located under ./src and that you are happy to use ./build for intermediary files (which is totally obliterated by the clean target so be careful).
Then 'make' or 'make jar' should generate the jar file.
NAME=MyProject
MAIN_CLASS=MyMainClass
SRC_DIR=./src
CLS_DIR=./build/classes
MANIFEST_FILE=./build/META-INF.MF
JAR_FILE=./$(NAME).jar
SRC_FILES=$(shell find $(SRC_DIR) -iname "*.java")
CLS_FILES=$(patsubst $(SRC_DIR)/%,$(CLS_DIR)/%,$(patsubst %.java,%.class,$(SRC_FILES)))
.PHONY: jar run clean mrproper
jar : $(JAR_FILE)
run : $(JAR_FILE)
java -jar $(JAR_FILE)
$(JAR_FILE) : $(MANIFEST_FILE) $(CLS_FILES)
jar cmf $< $# $(CLS_DIR)
$(MANIFEST_FILE) :
mkdir -p $(dir $#)
echo Main-Class: $(MAIN_CLASS) > $#
$(CLS_DIR) :
mkdir -p $(CLS_DIR)
$(CLS_DIR)/%.class : $(SRC_DIR)/%.java $(CLS_DIR)
javac -d $(CLS_DIR) -sourcepath $(SRC_DIR) $<
clean :
rm -Rf ./build
mrproper : clean
rm -f $(JAR_FILE)
Each time you execute Make it performs a find operation to get the list of source files, that might cause some delay depending on how many files and how fast is the file-system.... but you said is is a small project so it should not be an issue.
The double patsubst might well be compressed into a single one but I did it in two steps just in case.
Also notice that this solution compiles each Java class separately. This can be quite costly and it might be advisable to have another target to compile all at once ideally by creating a file that contains the name of all src java files and passing it to javac.
I used to work with Eclipse but switched recently to CodeRunner. The Problem is I'm supposed to use Graphviz, Batik and a Package from my college in order to work on some projects.
As long as there was one .jar file I'll managed to use my own with a simple:
RunCommand: java -jar stopndrop.jar $compiler
Arguments:
$1 Filename of the source file
$2 Encoding of the source file
$3 Compilation flags set in CodeRunner
$4 Path of a temporary directory
javac "$1" -d "$4"/java-compiled -encoding ${enc[$2]} $3 -cp stopndrop.jar
But now there is the Batik and College Folder with a bunch of Classes that are supposed to be loaded when they r needed.
My Question is: How do I do that?
Suppose that you have the following folder structure:
lib/
a.jar
b.jar
classes/
com/
foo/
Bar.class
Baz.class
And you need to link with all of these things to compile some code. Then you would specify as your classpath:
-cp lib/a.jar:lib/b.jar:classes
I have the following set up:
I have 4 packages:
root/src/terminal - has some java files
root/src/mail - has some java files
root/src/data - has some java files
root/src/main - has a single java file, Main.java
I also have the following files
root/bin - a folder to store .class files
root/mail.jar - a jar file which has important classes used in my code
Within the root, I would like to enter a terminal command which compiles root/src/main/Main.java and puts the class files in the root/bin location.
Can someone show me the command to do this? I'm on a Mac (running Leopard).
Here's the one liner:
cd /xyz/root
rm -rf bin/*
javac -d bin -classpath mail.jar -sourcepath src main/Main.java
Alternatively, you could use absolute directory names:
rm -rf /xyz/root/bin/*
javac -d /xyz/root/bin -classpath /xyz/root/mail.jar \
-sourcepath /xyz/root/src /xyz/root/ main/Main.java
In reference to Ant you said "I would rather keep it simple.".
In fact in the long term it is simpler to create a simple Ant build.xml file. The alternative is a bunch of non-portable scripts or batch file ... or lots of typing.
To run the application, assuming that you are still in the /xyz/root directory:
java -classpath bin:mail.jar main.Main
Or on Windows:
java -classpath bin;mail.jar main.Main
Or modify the above to use absolute pathnames in the classpath argument; e.g.
java -classpath /xyz/root/bin:/xyz/root/mail.jar main.Main
Without knowing your operating system?
What you should look into is using Apache Ant. It is a build tool that once installed and configured can utilize a build.xml file in your root to compile class files to a folder as well as package a jar file.
http://ant.apache.org/
try this:
javac -cp "/root/mail.jar;/root/src;" -d "/root/bin" Main.java
This is written hoping that you have package declarations in your classes from src folder like package terminal; and package main;.
See this: Options in javac command
Or use Apache Ant as suggested by maple_shaft.
From comment give by #maple_shaft:
In Unix, Linux operating systems the classpath separator is a colon instead of a semicolon.