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:
- They missed the cast to
(Object)
in the first call. - They inferred the type of
s1
to beString
, but forgot to add a cast to the call todoPrint
(so that the String version is called instead of the Object version). - One crappy one (I have not even listed) even infers the type of
s2
to be String, causing uncompilable code.
In any case, this code never calls the String
overload, but the decompiled code did.