Какова разница файлов Java .class между различными компиляторами, версиями, зависимостями? - PullRequest
1 голос
/ 28 марта 2011

Привет, мне было интересно, как сильно изменяются файлы классов 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 для определения версии компилятора и / или параметров, которые использовались при его компиляции?

Ответы [ 3 ]

5 голосов
/ 28 марта 2011

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

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

2 голосов
/ 28 марта 2011

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

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

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

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

1 голос
/ 28 марта 2011

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

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

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

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
    }
}
...