Look at this question. When you open .class file with scala plugin enabled (Intellij Idea) it shows you scala code, bu when it is turned off java decompile plugin shows you a decompiled java code. Note that .class files which are compiled by javac decompiles even when scala plugin is enabled. That means that scala plugin "look at" some marker inside class files and intercept file content showing.
What the marker it actually uses? Is there a way to open .class file and change compiler (and/or) other infomartion to make those classes looks like they are compied by javac?
Each class file can have a SourceFile attribute which contains the name of the source code file. Since this is an arbitrary string, it’s a bit about conventions, e.g. for Java source code, it usually contains the file name only, without any package specific directories.
So there still is bit of interpretation of the information, e.g. if the specified name ends with .java, an IDE has to look up the known source tree for a matching file in sub directories matching the actual package.
Determining that the source file is not Java is as simple as recognizing that it has a different file name ending, then, whatever convention is used for the particular language may be used, if a plugin knowing it has been installed. Otherwise, most IDEs will simply look for any text file of that name and display it. There might be LineNumberTable attributes, telling how bytecode instructions map to source line numbers, allowing debuggers to step through the code even without understanding the source code syntax. I already stepped through code compiled from an XSLT file that way.
Of course, the pattern of the specified source code file name may also be used to decide which decompiler to use when the source file has not been found.
Intellij Idea
Intellij IDEA (assuming your question is about this IDE), just figures out from which source file a binary was compiled, and then displays the corresponding source.
It does not extract or produce the source code from the binary. It is just able to find the source for a given binary. You can do this by matching file names and paths. Intellij does probably a bit more, though.
In general
In general, there is almost certainly no good decompiler that can produce Scala sources from class files. Also the source code is not embedded, so all you can achieve is trying to match source code files with binary files.
The Java code you get from decompilation is what you get shown when the IDE could not find the corresponding source file.
Related
(I couldn't figure out how to upload my screen capture to stackoverflow. So this is a streamable link: https://streamable.com/0im8tx)
In this video, VSCode opens QueriesController.class as opposed to QueriesController.java when I cmd click into QueriesController.
I have compiled provided the definitions of the jar file in my workspace:
"settings": {
"java.project.referencedLibraries": {
"include": [
"<path-to-jar-that-contains-QueriesController.jar>",
....
"sources": {
"<path-to-jar-that-contains-QueriesController.jar>": "/my/local/java/definition/src/folder",
Does anyone know why VSCode is choosing to open the definition as a .class file rather than a .java file?
I use commands to generate a simple jar package and use it in another project. It's true that when we click the class name, .class file is opened instead of .java file:
About how to generate a executable jar package, you can have a look at this reply:
Compile .java file and generate .class;
Generate manifest and pack them into jar
In general, a JAR (Java ARchive) is a package file format typically used to aggregate many Java class files and associated metadata and resources (text, images, etc.) into one file for distribution.
.java file isn't included in jar packages, and that's why you get .class file opened instead of .java file.
I am not familiar with VSCode but your problem is common across most IDEs.
Usually when a jar is made, it consists of compiled class files rather than original source codes. The reason for this is to run code as efficient and fast as possible and usually people don't want source code in jar because when running they also have to be recompiled again which is a waste of time.
Take a look at this picture. I have just downloaded a jar file from mavenrepository and it downloads the compiled version of jar. The extension is .class
What the IDE does is it tries to decompile the code with a decompiler (In this case as you can see FernFlower decompiler).
However it lacks formatting and in-code documentation the source code (.java) has. Which is why most IDEs offer to download sources. Intellij shows this right on top. Other IDEs may have this setting buried in deep. (You may have to check for yourself)
When you download sources, IDE try to contact the server and download original source code. Probably that would look something like this:
If you look closely you can see name has changed to .java which represents the source code.
VS Code has option under Java Settings, Java Download sources and Maven download sources.
It is not enabled by default. Upon enabling it, VS Code shows the proper source file, although the name appears to be .Class files.(Upon Ctrl + Clicking the symbol, with method implementations, comments, etc.,JavaDoc Comments)
If proper sources are not found in m2 repository, it shows the decompiled class file with stubbed methods. A comment similar to this is shown at the beginning of the file.
// Failed to get sources. Instead, stub sources have been generated by the disassembler.
// Implementation of methods is unavailable.
In Either of the cases, VS Code shows the maven library files as .Class files in read-only mode. Also, source files are not displayed on the Java Project Explorer.(Although even if it exists in the local .m2 repos).
Hope that helps! Happy Coding!
In my situation I have many .jar files being created from a build process. Before I do any debugging I want a way to quickly verify that my .java source matches the .class found in a .jar.
I figure that if I unzip the .jar and find the .class which matches my .java file then I should be able to determine if they're functionally the same.
How can I do this?
The first thing to realize is that compilation doesn't just use the specific .java file for the class being compiled. The compiler also uses information from the other .java and .class files available at compile time. For example, it may inline static final constants. Also, stuff like method overloading depends on which methods have been defined.
That being said, if you compile the same source file with the same compiler as before, you'll probably get the same, or a very similar class file. However, even with identical source files, different compilers (javac vs eclipse) and different versions of the compiler will produce different results.
Therefore, what I'd recommend is first try compiling everything and see if the classfiles match. If the class files don't match, try disassembling them with the Krakatau disassembler and do a diff on the diassemblies to see what the differences are. That will help you see if the difference is unimportant (such as a reordering of the constant pool) or if there are substantive changes to the bytecode.
You can use a java decompiler like http://jd.benow.ca/ in order to be able to view the corresponding source of your class file then you will be able to compare it with your java file
Maybe it would be enough for you if you can use a decompiler? Like one from IntelliJ IDE to see how is the source for you compiled class. You can even debug over the decompiled source.
I have a jar that I want to take out a class file and add a few lines of code to it. I got class editor, but you can't actually change any code, you can change constants and that is all. I have a program that you can read the source code from a .class but you can't change anything on it. Is there a program or eclipse plugin that you can read and EDIT the source code from a .class file?
Have a look at decompilers. They'll transform the java-bytecode back to source code. One example of such a compiler would be JD: http://jd.benow.ca/
After editing the source code you would have to compile the code again and pack it in the respective .jar file.
If your file is an old enough version, you can use jasper to disassemble it into bytecode, edit the bytecode and reassemble it using jasmin. Unfortunately these tools have not been updated in some time.
They do not produce Java code; you'll have to learn Java bytecode. But it is more reliable than the so-called "decompiler" methods.
As Java .class files are in byte-code format, you cannot modify them the way you would edit a .java source file. Bytecode is a low level language closer to the machine language rather than Java itself.
If you need to modify the source, one option is to use a decompiler, e.g. JAD (Java Decompiler), to get a source file and then change it and recompile to .class using javac. Make sure you figure out which version of Java language (1.4, 5, 6, 7, 8) has been used for the original jar file.
What you need for this is a java de-compiler. This will take the bytecode out of your class file and convert it back to its source. From there you will need to recompile the .java files that the de-compiler produces.
Here are some java de-compilers that I have seen:
http://dcompiler.sourceforge.net/
http://jd.benow.ca
What I don't get is how does Java know the methods of a jar that is referenced? If it is compiled just for running and you can't read it I don't see how you can see the methods still. An example of my question is like if you made a jar that makes a box show up on the screen using a method called
"ShowABox". And you add it to another Java project. Then how does the IDE know that a method called
"ShowABox" exists since the jar was already compiled? You can't read class files in an IDE so why can it read methods?
All the information you are referring to is actually stored in the class files precisely for this reason.
As to seeing the code in class files, you can certainly do so, and it will also prove that the information was kept. Have a look at Java Decompiler. Note you can even build this into eclipse if you want to see it directly there.
Compiled classes contain bytecode. Methods still has their real names, but their code compiled to JVM instructions.
You can read java class file format specification on wiki, read "The constant pool" paragraph, methods names (as other class information) contains in constant pool.
Just try to open some .class file in text editor, you will find methods names there. (.class files are often in project/bin folder, or open .jar as archive and get .class file from there)
A JAR is nothing more than all the class files zipped in a single file with a manifest attached. Each class file completely describes its public interface.
JAR-files have a very specific format — see http://en.wikipedia.org/wiki/JAR_(file_format) — and they contain class-files, which also have a very specific format — see http://en.wikipedia.org/wiki/Java_class_file. This format, in addition to providing the Java Virtual Machine with the information it needs to execute code, also provides IDEs and compilers with the information they need to find classes, interfaces, fields, methods, and so on.
A jar is nothing but an archive containing Java compiled .class binaries compressed for compactness into a single file. Its contents are compiled binaries organized in a directory structure. So you can think of it as a directory with files but compressed into a single archive (just like a zip file). A jar itself is not a binary ("exists since the jar was already compiled") -- it doesn't get compiled itself but it rather contains compiled elements.
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.