A little confusion about .jar files - java

In computer science I have learned that .jar files are basically a compressed set of .java files that have been compiled. So, when you have a project, instead of those 20 .java files you can have a pile of compressed classes (a .jar). Last year in CSI we worked with a .jar file called DanceStudio, which we had to use to make feet walk across the floor. This year, we are working with a different program to better understand java, so i unzipped the .jar file contained 26 classes, which I then decompiled. I wanted to try to create a program by compiling all of the .java files with the others necessary to make the program run (Walker, Foot, ETC.) When I try to compile all of these files, it will say that I have duplicate files (Walker, Foot, ETC.) What I don't understand is why this would compile if the .jar file was basically the same thing, just in a compressed form. What also confuses me is that the Foot, ETC files in the .jar are actually more complicated and have more code.
Could someone please explain how the .jar file actually works and separates these files apart, and how it could run with a duplicate class that isn't in the .jar file?

First of all, you're missing one step in your explanation of a .jar file.
A .jar file is a collection of .class files. And .class files are what is produced by compiling a .java file.
Usually a single .java file will produce a single .class file, because it will contain a single type definition. But there are several ways for a .java file to produce more than one .class files (inner/nested classes, anonymous classes, top-level non-public classes, ...), so it's not necessarily a 1-to-1 association between .java files and .class files.
Then there's the confusion why the decompiled Java source code looks more complicated than the original Java source. This one is easy to answer: the compilation step was not designed to be reversable.
When the Java compiler turns .java files to .class files it produces a format that is best suited for being executed. That format will not represent the exact same concepts that the Java source file does. For example: there's no classical "if" in the Java bytecode. It will be implemented be appropriate jump commands.
All of this means that the process of converting .class files back to .java files is complicated and usually non-perfect.

You generally compile your (clear text) .java source files into (binary) .class files.
If you use packages, then the class files will be in different subdirectories (representing the package).
A .jar file is a compressed binary file that puts all the .classes in the right directories in one compact, easy to manage file.
.jar file can also contain other files, such as manifests, bitmaps and resources.
.jar files can also be "signed" to insure the integrity/authenticity of their contents.
Here are some good links:
http://en.wikipedia.org/wiki/JAR_%28file_format%29
http://download.oracle.com/javase/tutorial/deployment/jar/
'Hope that helps

About your duplicate: Maybe your .jar is still in your build path, so when you try to compile your project with the decompiled class, you will have duplicate. check and remove the .jar if its still in your build path.

Related

Usage of jar with .java files and odd behavior of the compiler

I was curious about the differences between .jar with .class files and .jar with .java files. I partially got the answer here, But then what is the usefulness of .java files in the jar?
My guess is that the java files in the jar are like an interface that prevents compilation error, because I solved the IllegalAccessError thrown on runtime by replacing jar files with .class with jar files with .java specifically when using Xposed Framework. (Got the hint from this thread.)
Also
Thank you for your explanations and they were helpful. But I want to learn more about the differences in compiler's view, because I am wondering why my app works fine even if I only included the jar with java files, not class files (zxing). Also there are some cases that throws IllegalAccessException when I include the jar with class files, but not thrown when I include the jar with java files(xposed), even though I have to include at least one of them to make the compiler(AIDE) not complain about references, like unknown package. Why does the compiler not complain when I include only jar with java files though the compiler would not be able to resolve the actual implementation of the referred classes?
A .jar file is basically just a .zip file with another extension.
A .jar file with .class files have a special purpose and may have special meta-data (e.g. in META-INF folder).
A .jar file .java files is just a .zip file.
It is however common for open-source libraries to provide 3 .jar files:
One with .class files, to be used by your code, both to compile and to run your code.
One with .java files, to be used by your IDE, so you can drill into the library code and see it. Especially useful when stepping through the code with a debugger.
One with javadoc files (.html files), to be used by your IDE, so you can read the documentation about the classes and methods in the library. You do read the documentation, right?
None of those 3 files have to be named .jar. They could be renamed .zip so you could easily open them in your favorite Zip utility, or they could be renamed .foo just because...
They should be named .jar, to clarify that they are Java ARchives.
Its simple - *.java files are sources, *.class files are compiled classes.
What is used on runtime by JVM?? *.class files. Why would you put source files inside library? IDK, usally sources are distributed as separate jar, but all in all it is done to allow you to check library code without decompilation.

How do external java libraries(jars) actually work?

A lot of times in Java we want to use some functionality that is given to us in the form of JARs(ex. some external library). Most often than not I've noticed that JARs contain .class files.
Since .class files represent compiled bytecode ready for use by the JVM, my question is the following:
How is it that .class files are all that's needed for us to make use of an external library? Maybe a certain JAR contains the class file called: Person.class. How am I able to reference this class in my code when all that the JAR file exposes is a .class file. Isn't the source code(.java file) what's important and what's needed? In the same way that I can have two classes in the same package, I'm able to reference one from the other, because the two .java files(not .class files) are in the same scope(just to give an example).
Excuse me if it's a dumb question, but I really want to understand this.
Even if you write your source code in .java files, they are eventually compiled to form .class files which store bytecode that can be interpreted easily. When you use the jar files in your project, all the class files inside those jar files are included in your classpath, hence enabling you to use them.
So in a JAR package, .class files are sufficient to be used as a dependency.
The Java compiler takes your Java code, which is something that humans can understand, into .class files, which is something that the Java Virtual Machine (JVM) can understand. The JVM then takes the .class files and runs them on your machine.
A .jar file is effectively a collection of .class files packaged up (under the hood, it's really little more than a .zip in disguise). When you add a .jar onto your classpath, you are telling the JVM that it is one more place it should look when it needs a particular class.
I am not sure if I totally got your question, but the JARs are simply compiled javacode, which means, that the semantic/logic etc of the code has not been changed. You need to be able to access the functions/classes etc of the java code you want to use, because otherwise you would not gain any advantage of using a JAR.
One advantage of the JARs is, that the source code of these libraries is already compiled. Since these .class files are compiled .java files, they are all you need to access the functions that were written in the .java file.

Get all external source paths that a JAR uses

I have a problem with finding all the external libraries that a .jar file uses. My .jar file is very big, and manually decompiling it and going through every class, checking all the used paths is impossible. I wonder if there is a way or a tool that would go through a .jar file, and list all the external paths/links to classes that are not in the .jar file?
P.S: I'm not asking "what is the best tool to do so?", I just need to know how to get all the external paths a .jar file uses, without manually decompiling it.
Try this :
Extract the jar contents
Do a directory search for *.class piped to a text file.
Filter out inner and anonymous classes. (Class files names with $)
Write a small program that will simply loop through your list and load the class definition (Class.forName() should be enough)
Run the jar with option -verbose:class piped to a text file
Once your program is completed, you will have a full list of classes loaded from respective jars in the piped file
Filter out rt.jar contents for a more cleaner list
I'm not sure if -verbose:class works with obfustcated code, logically I think it should be fine.

Where does the actual java code reside if I export my jar without the source file?

I am familiar with the jar structure and it will have a .class files in the classes directory as well as META-INF directory containing the information to main().
But where does the actual java code resides in a jar?
Does it resides a compiled byte code? But don't different machines have different compilers?
I know that I can extract the java code using a decompiler which might be illegal. But I am not interested in doing so. I am more interested in understanding how code is stored?
Is it encrypted? If so, what is the encryption algorithm? what is the location inside the jar ?
Unless you specify otherwise, the source code is not included in the JAR file. The JAR file normally only contain class files (compiled JVM instructions), not source code.
A JAR file is just a ZIP file, renamed to mean Java ARchive.
You can check what's inside, unzipping it. If you're on a OS that doesn't allow you to decompress that archive because doesn't appear to be a compressed file, just change the extension to ZIP.
JAR files are not encrypted.
Java Sources are compiled in a platform-neutral Java bytecode, that's a kind of intermediate binary.
Once JVM load the classes it either interprets the bytecode or just-in-time compiles it to the underlying machine. JARs usually only contain that bytecode
Usually sources are not included in the JARs, especially for distribution. Some projects deliver sources as well in a separate archive. You should check with the provider of the JAR you're dealing with to get sources.
If decompiling is illegal or not depends on the terms of the license applied to JAR. You should check those.
Decompiling a class object is not a very easy task, but a guy used to do a very good job with his JAD.
Unfortunately it's no more maintained, but there are some websites where you can still download it.
Decompiled classes will not look exactly as the real sources, and you could have to make some changes, but you'll definitely get an idea about the source.

Eclipse: Is there a way to diff a jar and a project?

I have a .jar file that represents a plugin that I am trying to mess with. This is an older version of the plugin, and a newer version was written by somebody else. I have this newer version as a project.
The newer project is full of .java files, and the old plugin is full of .class files. I can import the jar as a project, but it's still all class files. The differences between the class files and the java files are not particularly large, and I would like to see the differences between them. When I do this now, however, the text comparison changes the .class file from its normal representation in the editor to a binary representation. I know that if they were the same type of file, I could select the two and hit "Compare With". How can I do this between a .class and a .java file, or how can I turn one into the other in a way that still allows me to compare the two?
What would really be best is if there were some way for me to edit the jar, by turning the .class files into .java files.
It seems like what you will need is a decompiler to convert the Java .class files (bytecode) back into their original .java source files (text). Then you could compare to the two text files. This seems like it might be useful: http://java.decompiler.free.fr
You can use SOOT (http://www.sable.mcgill.ca/soot/) to do this. Two approaches are possible:
Decompile the .class files into .java files using Dava in SOOT, and then compare the .java files.
Convert both .class and .java files into an intermediate representation called Jimple in SOOT, and compare the Jimple files.
I think the second approach is more reasonable, because:
In the first approach, some Java files are manually developed, while the others are machine generated. Doing a diff on them creates results that are difficult to read.
The Jimple representation is very close to Java source code and relatively easy to read. Reading a diff result on this unified, machine generated format is much easier. Also, if you want, you can convert all Jimple files back to Java source code (well, this is sort of the third approach...).
Because it was a plugin, I was able to import it as a plug-in project, and there was a box to include the source folder. When I checked that I got access to the .java code and was able to diff successfully.

Categories

Resources