Consider this (IMHO simple) example:
public class DecompilerTest {
public static void main(String[] args) {
Object s1 = "The", s2 = "answer";
doPrint((Object) "You should know:");
for (int i = 0; i < 2; i++) {
doPrint(s1);
doPrint(s2);
s1 = "is";
s2 = new Integer(42);
}
System.out.println();
}
private static void doPrint(String s1) {
System.out.print("Wrong!");
}
private static void doPrint(Object s1) {
System.out.print(s1 + " ");
}
}
Compile it with source/target level 1.1 without debug information (i.e. no local variable information should be present) and try to decompile it. I tried Jad, JD-GUI and Fernflower, and all of them got at least one of the call wrong (i. e. the program printed "Wrong!" at least once)
Is there really no java decompiler that can infer the right casts so that it will not call the wrong overload?
Edit: Target level 1.1 so that there is none of that Java6-specific fast-validation information present. That might give the decompiler a clue that s1 has been declared as Object
and not as String
. Decompilers should be able to decompile the code even without this information (not necessarily get the original variable type, but show the same behaviour), especially since lots of obfuscators strip it as well.
What decompilers got wrong:
(Object)
in the first call.s1
to be String
, but forgot to add a cast to the call to doPrint
(so that the String version is called instead of the Object version).s2
to be String, causing uncompilable code.In any case, this code never calls the String
overload, but the decompiled code did.
Short answer: 99% of the time, decompiled code will not look like the original code, but it should behave the same way.
It is also not possible to decompile all programs. Furthermore, it is not easy to separate data and code because both are represented similarly in most current computer systems. A type of reverse engineering, a decompiler performs the opposite operations of a compiler.
The main function is to disassemble the . class files. JAD can be deployed from the console, and it will decompile Java classes into the source code. This way, developers can look deep into the code of Java runtime libraries and even beautify the lines, preparing them for a recompilation.
Krakatau correctly handles all overloaded methods, even methods overloaded on primitive types, which most decompilers get wrong. It always casts arguments to the exact type of the called method, so the code may be more cluttered than necessary, but at least it is correct.
Disclosure: I am the author of Krakatau.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With