Файл класса, сгенерированный javac, всегда один и тот же? - PullRequest
6 голосов
/ 29 марта 2012

В настоящее время мы переписываем всю нашу систему сборки для большого проекта (около 2000 исходных файлов), и ведутся разговоры о бинарном сравнении файлов, чтобы убедиться, что все правильно, что приводит кследующий вопрос: Гарантируется ли вывод javac одинаковым во всех компиляциях или он может быть изменен?

Другой вопрос подразумевает, что постоянный пулможет иметь другой порядок, но при условии, что мы можем контролировать порядок файлов, входящих в вызов javac, все еще существует вероятность различий?Мы используем Ant и Maven как часть сборки, если это может повлиять и на вещи.

Ответы [ 3 ]

3 голосов
/ 30 марта 2012

Байт-код абсолютно , а не гарантированно будет таким же; с одной стороны, компиляторам разрешено выполнять оптимизации, которые не влияют на гарантированное поведение. Спецификация языка Java даже упоминает, в некоторых местах, оптимизации, которые может выполнить компилятор; например, оператора конкатенации строк + отмечает, что:

Реализация может выбрать выполнение преобразования и объединения за один шаг, чтобы избежать создания, а затем отбрасывания промежуточного объекта String. Чтобы повысить производительность многократной конкатенации строк, компилятор Java может использовать класс StringBuffer или аналогичный метод для уменьшения числа промежуточных String объектов, которые создаются путем вычисления выражения.

[ ссылка ]

0 голосов
/ 30 марта 2012

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

0 голосов
/ 30 марта 2012

Я не эксперт по компилятору, но я склонен полагать, что другие ответы говорят, что двоичное сравнение не является надежным на 100%.

Я бы рассмотрел другую альтернативу: вы должны быть в состоянии проверить артефакты, создаваемые вашей системой сборки (.jars & .wars и т. Д.), И убедиться, что у каждого есть ожидаемое содержимое, и даже что размер каждого файла равен в довольно жестких допусках.

Если ваш скрипт сборки генерирует исходный код и компилирует его, то вы должны быть в состоянии сделать сравнение с сгенерированным исходным кодом, что, как я ожидаю, будет стабильным на 100% от сборки к сборке. (Или, по крайней мере, предсказуемо).

Надеюсь, это поможет!

...