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.
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.