Why my compiled class has it's methods local variables renamed? - java

I have a Kitchen.jar file. I need to modify a class inside it. I decompile it with JD. Then I modify the Toster.java file and compile it with:
javac -classpath . Toster.java
And then I take it back into the Kitchen.jar with:
jar -uf Kitchen.jar Toster.class
All works except for one problem. When I open updated Kitchen.jar in JD I see that local variables inside all methods are renamed to something like localLongVar. Why?
The reason I ask is because Kitchen.jar refuses to work after the modification. And I suspect it has to be the compilation problem. Maybe I've misused some flags or anything. Not sure. I have no knowledge of Java whatsoever, except for the basic syntax.
My guess is that I compile it with latest 1.7 version and original jar is compiled with older JDK. That may explain failure of operation, but that doesn't explain the renaming of locals.
EXAMPLE
The random line from the original jar:
BigInteger[] result = new BigInteger[bis.length / 2];
And the very same line of my class:
BigInteger[] arrayOfBigInteger1 = new BigInteger[paramArrayOfBigInteger.length * 2];
So its result vs arrayOfBigInteger1.

By default javac removes debugging information other than source file and line number. Compile with javac -g or javac -g:vars.
From the documentation of javac
-g Generate all debugging information, including local variables. By default, only line number and source file information is generated.
-g:none Do not generate any debugging information.
-g:{keyword list} Generate only some kinds of debugging information, specified by a comma separated list of keywords. Valid keywords are:
source Source file debugging information
lines Line number debugging information
vars Local variable debugging information

The names of the variables are not preserved in compiled code. Most obvious to reduce the size of the compiled class. The compiler will replace them by shorter names. Doing this is also good for obfuscating the code so that someone who decompiles the code has problems to understand the logic. The localLongVar you see in JD is what the compiler makes of the replaced variable names.

Related

How to compile and run java programs ignoring package info?

I have a pile of .java files. They all have the same class name public MyClass. They all have a main method. They all may or may not have a package declaration at top, and I do not know ahead of time.
I am trying to write a script to compile and run these java programs. This is easy for the files without the package declaration... I just do some cp operations to setup, javac MyClass.java and java MyClass, then rm to teardown. However, the files with the package declaration require special attention. I have a few options that occur to me, including deleting the package lines, or attempting to read the package lines so that I know what the resulting directory structure should be. Both of these require me to go parsing through the .java files, which makes me sad.
Is there a way to compile and run these files without having to parse the .java files? Something like:
javac --ignore_package_structure MyClass.java
would be ideal, but a quick look at the javac man pages suggests that such a thing doesn't exist.
If we can assume that each student submits a single source file named HelloWorld.java, then we can use the "Launch Single-File Source-Code Programs" feature added by JEP 330 in Java 11:
java HelloWorld.java
We don't run javac first, we don't get a .class file (no cleanup needed), and any package declaration is handled automatically.
Remember, the students are still allowed to use many classes, they just all have to be submitted to you in a single source file.
The name of the class doesn't even matter. The first class in the source file is executed.
There isn't any easy way to do this. You could use regex though, and replace all imports with this simple java regex:
"package \w+;"g
Simply stated, you create a Java program to replace all the package names.
How to replace files: Find and replace words/lines in a file

Java: Class files containing source code?

I was inspecting the class file format since I wanted to add source code to the class file (which was possible in early Java versions) but all I found was a SourceFile attribute and the SourceDebug attribute. I was looking for the complete source code of the class to be bundled with the class file to ease the post-processing pipeline.
Does anyone know if my memories are wrong or how I can bundle the complete source code of a class within the class file so that I do not have to look up for the java-file when I want to check the source code?
Is there a compiler switch to do that?
Javac has a -g option adding additional debug information. Can someone tell me whats are the information it adds? Without the -g switch it generates lines of code index and source file information.
The main problem I have is generate a class file but only have a reference to a source file that might change. I want simply to bundle up source and class file.
In maven I can simply copy over all the source files to the target directory but would might be incompatible with Eclipse, IntelliJ and NetBeans IDE (and what not)... .
Using a decompiler will also provide a way to extract a useful representation of the source code since most decompiler will value the lines of code information and position the decompiled structures accordingly within the source code.
Since some scenarios will require access to comments and a correct representation on a char by char level, the decompiler would be a second rate solution.
One possible solution I found is defining a new class-file attribute (which is legal) that contains the source. Since the source is huge when compared to the class file, the content might be best compressed (yielding a 1:5 to 1:10 ratio).
This way the class file and the sources stay bundled.
The JVM specification guarantees that every JVM/Tool has to ignore unknown attributes.
I will invest into a wrapper of javac application, that ensures the source was not modified during compilation (and if yes, redo the compilation process) and after compilation is done adding the source code as a class-file attribute.
Since this will be incompatible to the IDE-build cycle of Eclipse (and most likely IntelliJ and NetBeans) it will also require a special post processor.
So integration will also require alternatives to the JavaBuilder.
Once the source code is attached to the class file in question it is very easy to do a lot of advanced stuff with it that helps with both maintaining and managing code. For me its important that the source code and a class stay together and the source information is a 100% percent equal to the source code it was compiled from.

How is the stacktrace printed when the program is compiled?

This is a very simple question:
When you compile a java program, it is converted to byte code, so therefore, every line number of the .java or .class file is missed (I think so, probably I am wrong..). So, when you print a stack trace, how does it manage to get all the class names and line numbers that were in the call stack? I think that I may be missing something here, but I couldn't find anything related to this.
When you compile a java program, it is converted to byte code
Correct.
so therefore, every line number of the .java or .class file is missed (I think so, probably I am wrong..).
You're wrong. Line number information is embedded into the .class file unless you use the -g compiler option in certain ways.
If line numbers are present, then the java compiler created bytecode with the debug flag set to true. This can be achieved using java -g
From Oracle's javac documentation:
-g
Generate all debugging information, including local variables. By default, only line number and source file information is generated.
-g:none
Do not generate any debugging information.
-g:{keyword list}
- Generate only some kinds of debugging information, specified by a comma separated list of keywords. Valid keywords are:
source
Source file debugging information
lines
Line number debugging information
vars
Local variable debugging information

Java decompiler is not giving full source code

I have tried to decompile .class file with JD. BUt i got Strange code in it(Static call to a non static method, Classname.this.method etc.) .
Could you please tell me whether it will give 100 percent source code or not?
No, java decompilers can't give you the exact source code back. Many compiler optimizations will not be reflected back in the generated file.

Deserialize objects - class changed

I serialized an array of objects in the past without a serialUID, but in the meantime I have changed the class- I added a boolean.
Now I can't restore the objects.
I've tried to recreate the old class (from svn) and removed the warning about "no serial uid" so as to get the serialUID generated from Eclipse. I tried pasting this into my new version of the class, but it still fails. I'm not sure if this is because removing the warning changes the generated serialUID.
Next I tried to use the tool "serialver", but I keep getting a "class not found" error.
Could someone spell out for me what I should type in the commandline, as I'm not entirely sure what to type in the classpath?
I used this as my template:
serialver -classpath C:\foo\classes.jar com.bar.FooMessage
My workspace is D:\blabla\androidworkspace
Project is Shows so in eclipse it says:
Shows-src-xyz-show.java
and I run the command from C:\Program Files (x86)\Java\jdk1.6.0_24\bin
Here is good explanation how serialization works http://www.javaworld.com/community/node/2915
what you need to do is:
get serialized bytes and analyze them,
those bytes contains your original class serial number,
then you should set serial number to you code and compile
like static final long serialVersionUID = ;
Run the serialver utility on the original .class file. That will tell you its computed serialVersionUID. Then edit the new source to declare that.
I found one example here http://rchandratech.blogspot.com/2015/05/using-serialver-jdk-command.html,
Try in Eclipse, from command line go till project/bin where the class file is located, then serialver -classpath "./" com.xxx.xxx.

Categories

Resources