Какие настройки влияют на компоновку скомпилированных файлов Java .class? Как вы можете определить, равны ли два скомпилированных класса? - PullRequest
4 голосов
/ 13 марта 2009

У меня есть приложение, которое было скомпилировано с помощью встроенной задачи Eclipse «Compile». Затем я решил перенести процедуру сборки в Ant's javac, и в результате были получены файлы меньшего размера.

Позже я обнаружил, что, настроив уровень отладки на "vars,lines,source", я мог встроить ту же отладочную информацию, что и Eclipse, и во многих случаях файлы оставались точно такого же размера, но внутренняя компоновка была другой. И, как следствие, я не мог использовать сигнатуры md5sum, чтобы определить, были ли они точно такой же версией.

Помимо отладочной информации, что может быть причиной того, что 2 предположительно равных файла имеют разную внутреннюю разметку или размер?

А как вы можете сравнить скомпилированные файлы .class?

Ответы [ 8 ]

3 голосов
/ 13 марта 2009

Нет обязательного порядка для таких вещей, как порядок записей константного пула (по существу всей информации о символах), а также атрибуты для каждого поля / метода / класса. Разные компиляторы могут писать в любом порядке.

Вы можете сравнивать скомпилированные классы, но вам нужно будет изучить структуру файлов классов и проанализировать ее. Есть библиотеки для этого, например BCEL или ASM , но я не уверен на 100%, что они помогут вам в том, что вы хотите сделать.

2 голосов
/ 14 марта 2009

Важно отметить, что Eclipse не использует javac. Eclipse имеет свой собственный компилятор, JDT , и поэтому различия в результирующих файлах .class меня не удивляют. Я ожидаю, что они не будут дословными, потому что они разные компиляторы.

Из-за их различий существует код, который компилируется с использованием javac, но не JDT, и наоборот. Как правило, я видел различия в этих двух, которые становятся очевидными в случаях интенсивного использования генериков

2 голосов
/ 14 марта 2009

Плагин ASM Eclipse содержит средство сравнения байт-кода. Вы выбираете два класса, щелкаете правой кнопкой мыши и делаете байт-код «Сравнить с / каждым другим».

1 голос
/ 13 марта 2009

Для сравнения вы можете декомпилировать файлы классов и воспроизводить сгенерированные источники. Смотрите это .

1 голос
/ 13 марта 2009

как сказал Майкл Б., оно может быть произвольным.

Я работаю на системах, которые используют размеры файлов в качестве безопасности. Если размер файлов .class изменится, классу не будут предоставлены определенные разрешения.

Обычно это было бы легко обойти, но у нас достаточно полный контроль над средой, так что это на самом деле довольно функционально.

Во всяком случае, всякий раз, когда просматриваемые классы перекомпилируются, кажется, мы должны пересчитать размер.

Другое дело - при компиляции файла генерируется специальный номер ключа. Я не знаю много об этом, но это часто мешает классам работать вместе. Я считаю, что процедура, скомпилируйте класс A и сохраните его (назовите его a1). Снова скомпилируйте класс a (a2). Скомпилируйте класс b против класса a2. Попробуйте запустить b против a1. Я считаю, что в этом случае он потерпит неудачу во время выполнения.

Если бы вы могли узнать больше об этом номере ключа, он может дать вам информацию, которую вы ищете.

1 голос
/ 13 марта 2009

Что наиболее важно, слоты стека для локальных переменных могут быть расположены произвольно без изменения семантики кода. Таким образом, в принципе, вы не можете сравнивать скомпилированные файлы классов без их анализа и нормализации - довольно много усилий.

Почему ты так хочешь?

0 голосов
/ 13 марта 2009

В конечном счете используемые конфигурации, вероятно, имеют значение. Предполагая, что они используют одни и те же версии Java, существует множество параметров, доступных для конфигурации компиляции (соответствие JDK, совместимость файлов классов и множество параметров отладочной информации).

0 голосов
/ 13 марта 2009

Eclipse выполняет инструментарий для работы в отладчике?

...