Есть ли какой-нибудь декомпилятор Java, который может правильно декомпилировать призывы к перегруженным методам? [закрыто

StackOverflow https://stackoverflow.com/questions/2840183

  •  27-09-2019
  •  | 
  •  

Вопрос

Рассмотрим это (IMHO простой) пример:

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, и все они получили хотя бы один из звонков не так (то есть программа напечатанной «неправильно!», По крайней мере, один раз)

На самом деле нет Dava Decompiler, который может вывести правильные отливки, чтобы он не назвал неправильную перегрузку?

Редактировать: Целевой уровень 1.1, так что не существует ни одного из этого, не специфичная Java6. Это может дать декомпилярную подсказку, что S1 был объявлен как Object и не как String. Отказ Декомпилы должны быть в состоянии декомпилировать код даже без этой информации (не обязательно получают исходный тип переменной, но показывают одно и то же поведение), особенно поскольку множество комфортных блоков.

Какие декомпилы ошиблись:

  • Они пропустили (Object) в первом звонке.
  • Они выводят тип s1 быть String, но забыл добавить литой на звонок doPrint (Так что строковая версия называется вместо версии объекта).
  • Один дерьмовый (я даже не перечислял) даже не подразумевает тип s2 быть строкой, вызывая неразлым код.

В любом случае этот код никогда не называет String Перегрузка, но декомпилируемый код сделал.

Это было полезно?

Решение

Кракатау Правильно обрабатывает все перегруженные методы, даже методы перегружены на примитивные типы, которые большинство декомпилеров не так. Он всегда бросает аргументы на точный тип называемого метода, поэтому код может быть более загроможден, чем необходимо, но, по крайней мере, это правильно.

Раскрытие: Я автор Кракатау.

Другие советы

Hallo Mihi,

Извините за поздний ответ. Я копирую свой ответ от http://www.reversed-java.com/fernflower/forum?threadfolder=2_de.

Ваша проблема на самом деле хорошо известна. Давайте посмотрим:

1) Чистый базовый код не содержит никакой информации о типе переменных объектов, поэтому в первом проходе S1 и S2 объявляются как объект.

2) Decompiler старается упорно назначать наилучший тип для каждой переменной (= «самый узкий принцип типа», реализованный в Fernflower). Таким образом, S1 и S2 правильно идентифицированы как экземпляры строки.

3) Вызов DoPrint Дайте нам прямую ссылку на правильный метод
Частный статический пустотный допринт (объект S1)

4) Все в порядке, верно? Теперь у нас есть строковая переменная S1, передаваемая на функцию, которая ожидает объекта. Нам нужно бросить это? Не так же, как вы думаете, так как объект является супер-типом строки. И все же мы делаем - потому что в одном классе есть другая функция с тем же именем и другой подписью параметров. Поэтому нам нужно проанализировать весь класс, чтобы узнать, необходим ли актерьер или нет.

5) Вообще говоря, это означает, что нам нужно проанализировать все ссылки на все библиотеки, включая Java Runtime. Огромная нагрузка на работу! Действительно, эта функция была реализована в некоторой альфа-версии Fernflower, но не сделала ее в производстве, но из-за производительности и наказания на память. Другие упомянутые декомпилы не хватает этой способности по дизайну.

Надеюсь, я немного уточнил вещи :)

Плагин Jadclipse Eclipse для декомпиляции также предоставляет Jode Decompiler, который вы можете попробовать. Я использую это, когда Jad сдается.

Также Dava Decompiler использует сажи, который - в прошлый раз я выглядел - был очень амбициозным в реконструировании оригинального кода Java. Я не пытался с вашим примером, но вы можете посмотреть. http://www.sable.mcgill.ca/dava/

Пропионский Должен обрабатывать перегруженные вызовы метода правильно. Как и Кракатау, Procyon изначально вставляет отливки для каждого аргумента метода, который точно не соответствует целевому методу. Однако большинство из них будут удалены во время более поздней фазы декомпиляции, которая идентифицирует и устраняет избыточные касты. Procyon будет удалять кастрюли только на вызове аргументов, если он может убедиться, что это не приведет к привлечению к привязку вызова к другому способу. Например, если .class Объявление метода не может быть разрешено, он не будет пытаться вообще удалить отливки, потому что он не имеет способов узнать, какие перегрузки могут быть конфликтуют.

Добавление к предыдущим ответам: вот список современных декомпилеров по состоянию на март 2015 года:

  • Пропионский
  • Овладеть
  • Jd.
  • Fernflower

Все они поддерживают перегруженные методы.

Вы можете проверить вышеупомянутые декомпилы онлайн, установка не требуется и сделать свой собственный образованный выбор. Java Decompilers в облаке: http://www.javadecompilers.com/

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top