Рассмотрим это (имхо) простой пример:Есть ли какой-нибудь Java Decompiler, который может правильно декомпилировать вызовы перегруженным методам?
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 + " ");
}
}
Собирать с источником/целевого уровня 1.1 без информации отладки (т.е. не локальной переменной информации не должно присутствовать) и попытаться декомпилировать его. Я попробовал Jad, JD-GUI и Fernflower, и все они получили хотя бы один из неправильных вызовов (например, программа напечатала «Неправильно!» Хотя бы один раз)
Действительно ли нет декомпилятора java, который может вывести правильное бросает так, чтобы он не вызывал неправильную перегрузку?
Редактировать: Целевой уровень 1.1, чтобы не было никакой информации о быстрой проверке Java6. Это может дать декомпилятору ключ к тому, что s1 объявлен как Object
, а не как String
. Декомпилятор должен иметь возможность декомпилировать код даже без этой информации (необязательно получить исходный тип переменной, но показывать то же поведение), тем более, что множество обфускаторов также разделяет его.
Что декомпиляторов ошибались:
- Они пропустили бросок к
(Object)
в первом вызове. - Они вывели тип
s1
какString
, но забыли добавить приведение к вызовуdoPrint
(так что вместо версии объекта вызывается версия String). - Один из дерьмовых (я даже не перечислял) даже указывает тип
s2
на строку, вызывающую несовместимый код.
В любом случае этот код никогда не вызывает перегрузку String
, но декомпилированный код сделал.
Что значит «они ошиблись»? Какой источник они генерируют после декомпиляции? – skaffman
hm, и почему 1.1? – Bozho