Какова разница между файлами java .class в разных компиляторах, версиях, зависимостях?

Привет, мне было интересно, насколько файлы классов Java меняются в разных компиляторах. Итак, насколько меняются фактические байты, если файлы .java скомпилированы, скажем, Sun JDK 1.4, 1.5 1.6 или даже IBM JDK. Я знаю, что файлы классов могут отличаться в отношении отладочной информации и запутывания, но давайте предположим, что эти параметры одинаковы, поэтому включена отладочная информация, без запутывания. Если бы я запустил MD5 или SHA-1 в файле .class, который был скомпилирован JDK 1.4, был бы хэш другим, если бы я скомпилировал его в JDK 1.5, но с таргетингом на 1.4, что при нацеливании на JDK 1.5?

Также в связи с этим изменяется ли двоичный файл файла класса при использовании разных зависимостей или по-разному задается вопрос: может ли двоичный файл файла класса измениться в зависимости от его зависимостей?

И последнее, но не менее важное: существуют ли программные способы анализа метаданных файла .class для определения версии компилятора и/или переключателей, которые использовались при его компиляции?


person AGrunewald    schedule 27.03.2011    source источник
comment
MD5 и SHA-1 определены таким образом, что они изменяют около половины своих выходных битов, если вы изменяете один входной бит. Другими словами, если эти файлы классов отличаются хотя бы одним байтом, вы получите совершенно разные MD5 или SHA-1.   -  person pajton    schedule 28.03.2011


Ответы (3)


Компиляторы Java имеют некоторую свободу при создании классов и байт-кода из исходного кода. Они могут переупорядочивать методы, переупорядочивать пул констант (с именами классов, именами методов и строками — это также приводит к различному байт-коду метода) и переупорядочивать фактические команды байт-кода, если результат их выполнения тот же.

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

person Paŭlo Ebermann    schedule 28.03.2011

Формат файлов классов см. на http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html

Да, файлы классов могут изменяться и обычно изменяются в зависимости от того, какой конкретный компилятор используется для их создания. Есть много деталей реализации компилятора, которые приведут к другому байт-коду, например. перечисление зависимостей в разном порядке в массивах interfaces[] или fields[]. Плюс компиляторы могут свободно использовать различные оптимизации.

Добавление или удаление оператора «import» не обязательно меняет файл класса, но использование класса в одном пакете, а не в другом, безусловно, изменит. Не уверен, что это отвечает на ваш второй вопрос.

Я не верю, что компиляторы оставляют свою идентичность в файлах классов. Любой такой анализ должен быть косвенным и, скорее всего, эвристическим (в строках, говорящих автору книги по ее стилю) - если только у вас нет исходного кода и вы не можете скомпилировать с каждым компилятором и сравнить.

person jsalvata    schedule 28.03.2011
comment
добавление или удаление импорта само по себе не изменяет зависимости. На самом деле импорт вообще не является зависимостью. Фактическое явное или неявное использование внешнего класса или члена класса создает зависимость. (И есть несколько способов получить зависимость без импорта.) - person Stephen C; 28.03.2011

Павел хорошо ответил на ваш вопрос о хешировании. Что касается вашего другого вопроса:

Также в связи с этим изменяется ли двоичный файл файла класса при использовании разных зависимостей или по-разному задается вопрос: может ли двоичный файл файла класса измениться в зависимости от его зависимостей?

да. Файл класса содержит сигнатуры для всех вызываемых методов, и они могли измениться. Рассмотреть возможность:

void test() {
    Foo.bar(1,2);
}

где Foo в версии 1 определяется:

class Foo {
    public static void bar(int x, int y) {
        // do something
    }
}

и в версии 2:

class Foo {
    public static <T> T bar(T... ts) {
        // do something
    }
}
person meriton    schedule 28.03.2011