Являются ли декомпилированные JAD-файлы точными на 100 %?

Являются ли файлы, декомпилированные JAD, точными на 100%. Я декомпилирую некоторые jar-файлы, чтобы получить исходный код, и когда я пытаюсь собрать проект с этими java-файлами, он не показывает точную сборку. Я делаю это неправильно или декомпилированные файлы не точно такие же, как исходные?


person nikhilgupta86    schedule 16.05.2014    source источник
comment
Исходный файл может быть запутан. В любом случае попробуйте использовать jd-gui   -  person Marco Acierno    schedule 16.05.2014
comment
нет, нет комментариев, имен локальных переменных (если у вас нет отладки), исходных номеров строк, исходных констант времени компиляции, исходного форматирования и т. д. Все это потому, что они не находятся в байтовом коде.   -  person Peter Lawrey    schedule 16.05.2014
comment
Байт-код для while() {} и for() {} нечетко различим, декомпилятор может заменить один другим (семантика остается прежней). Некоторый байт-код невозможно правильно декомпилировать в java (например, сгенерированный код, код, сгенерированный другими компиляторами языков на основе VM).   -  person Durandal    schedule 16.05.2014
comment
Кроме того, компилятор создает вспомогательные методы для работы внутренних классов (см. это)   -  person vlp    schedule 20.09.2015


Ответы (2)


Краткий ответ: в 99% случаев декомпилированный код не будет выглядеть как исходный код, но он должен вести себя так же. Таким образом, предполагая, что декомпилятор не делает ошибок, он должен быть точным в работе, но не в реализации.

Длинный ответ: когда компилятор Java переводит ваш исходный код в байтовый код, он выполняет определенные операции, которые изменяют внешний вид кода. Я не эксперт в деталях компилятора Java, но простая оптимизация, которую выполняют многие компиляторы, заключается в вставке небольших методов в то место в коде, где они вызываются.

Например, допустим, мы компилируем этот код:

public class c
{
   public int add(int a, int b)
   {
      return a + b;
   }

   public static void main(String [] args)
   {
      int i = add(1, 2);
   }
}

Поскольку b — это только одна строка, и ее можно безопасно заменить своим содержимым, умный компилятор может изменить основной метод на это:

public static void main(String [] args)
{
   int a = 1, b = 2
   int i = a + b;
}

или это:

public static void main(String [] args)
{
   int i = 1 + 2;
}

Это было бы сделано, потому что накладные расходы на вызов метода хуже, чем накладные расходы на помещение содержимого метода непосредственно в то место, где он вызывается.

Я понятия не имею, что компилятор Java сделал бы в этой ситуации, но он вносит подобные изменения в код. Это не обязательно неточно, потому что делает то же самое, что и исходный код. Поскольку компилятор не оставляет подробностей об этих изменениях нигде в файле .class, декомпилятор не может узнать, выполнялась ли оптимизация в какой-либо данной точке кода или была ли она написана таким образом.

Есть также ряд других вещей, которые могут не пережить переход на байтовый код (например, имена переменных и комментарии).

Так что да, когда вы смотрите на декомпилированный код, вы смотрите на то, как выглядит файл .class, а не на то, как выглядит файл .java. Несмотря на то, что это кажется неточным, он должен работать так же.

person Community    schedule 16.05.2014
comment
Сам компилятор Java не выполняет встраивание так, как вы описали. Он мог бы теоретически сделать это, если бы метод был private, но даже в этом случае он не сделает такого изменения, потому что он должен сохранить структуру класса (например, для случая, когда метод доступ осуществляется через отражение). Встраивание выполняется JIT. - person Marco13; 16.05.2014
comment
Да, я не изучал внимательно компилятор Java, поэтому я не был точно уверен, что использовать в качестве примера. Я выбрал этот, потому что его было легко объяснить, и он дает понять, что изменения вносятся в структуру кода, даже если это не так применимо к Java, как к другим платформам. Если у кого-то, кто больше знает о компиляторах Java, есть лучший пример, я был бы рад добавить его (или изменить свой ответ на вики сообщества). - person RyNo; 16.05.2014
comment
Наиболее распространенные различия, которые вы увидите, будут незначительными изменениями в ветвлении, например, вы можете увидеть while(a) { if (!b) f(); } там, где автор изначально написал while(a) { if (b) continue; f(); }, или a = b ? c : d там, где автор написал if (b) a = c; else a = d;. Вы можете увидеть больше промежуточных переменных и встроенных значений. Но вы не должны никогда предполагать, что декомпилированный вывод функционально эквивалентен исходному коду. Так и задумано, но декомпиляторы не безошибочны. - person Mike Strobel; 16.05.2014
comment
@MikeStrobel Я изменил свой ответ на вики сообщества, поскольку вы, ребята, доказали, что я недостаточно знаю о компиляторах Java, чтобы написать хороший ответ. Не стесняйтесь улучшать его. - person RyNo; 17.05.2014

Если в этой программе больше частных занятий. Декомпилятор перевернет код по-своему, но если их меньше, то он покажет правильный код. В случае xml-файлов он преобразует полностью....

person Aadarsha SUbedi    schedule 18.09.2015
comment
Это очень расплывчатый и, вероятно, неправильный ответ. Не могли бы вы предоставить более подробную информацию или источник вашего утверждения? - person lukelazarovic; 18.09.2015