2017-02-01 5 views
3

Я пишу свои функции Лямбды AWS в Java. Инструмент, который я использую для загрузки своих lambdas (Terraform), хочет использовать хэш SHA-256 моего файла jar, чтобы отслеживать, нужно ли загружать новую версию лямбды.Как использовать javac для создания двоичных идентичных файлов классов на разных платформах?

Проблема заключается в том, что разные JDK на разных платформах ОС (Windows и Linux) создают немного другой байт-код (даже при использовании той же «версии обновления JDK»). Это означает, что если я загружу лямбду в Windows, перезапустите процесс в Linux - он обнаружит другой хеш-код для банки и повторно загрузит лямбда-банку без необходимости.

Вопрос: Как заставить javac создать идентичный байт-код на разных платформах ОС?

+4

Немного отличается как? – EJP

+1

^Это. Можете ли вы предоставить два примера .class-файлов? – Marco13

+0

Немного отличается в двоичном содержимом. Когда я их различал в winmerge, некоторые из нетекстовых байтов были разными. Я попытаюсь опубликовать снимок экрана. – Shorn

ответ

3

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

Поскольку в каждом прогоне нет необходимости создавать точно такой же файл, реализация компилятора даже не пытается. Справедливости ради следует предположить, что при выполнении одного и того же программного обеспечения с точно таким же входом (не только с одним и тем же исходным кодом, но и с теми же параметрами) он будет выдавать одинаковый вывод, но для этого требуется не только одна и та же версия компилятора, но также те же JRE.

К сожалению, может быть быть по-разному, даже с тем же внедрением и вводом. Например, были попытки рандомизировать хеширование java.util.HashMap в некоторых реализациях Java 7, и было бы неудивительно, если javac хранит определенные артефакты в HashMap. Это не относится к Java 8, но может применяться к неизменяемым картам, которые будут внедрены в Java 9. Будет ли компилятор использовать эту функцию, не предсказуем.

Итак, если вы нашли конкретную версию jdk, которая воспроизводимо генерирует точно такой же байт-код, вы можете быть в порядке с ней сейчас, но должны знать, что следующая версия может не иметь этого свойства.

До сих пор не было рассмотрено, что даже наличие того же байткода не гарантирует наличие того же файла jar, поскольку порядок файлов в файлах jar не указан. Это может зависеть от системного порядка итераций файлов. Кроме того, поскольку файлы jar являются zip-файлами, в которых хранятся временные метки, недавно скомпилированный файл класса определенно дает другой файл, если только вы не предпринимаете дополнительных мер, например. обеспечить соблюдение определенной отметки времени для всех записей.

2

Для любого органа, который натыкается на этот вопрос:

  • первое, что нужно смотреть на это, чтобы проверить поставщику JDK на каждой платформе

Оказывается, у меня была та же версия/уровень обновления, но фактически использовал разные JDK (duh).

Я использовал Oracle JDK для Windows и OpenJDK для Linux. Как только я сменил их на Azul Zulu JDK (u112) как на Windows, так и на Linux - кажется, что создается тот же самый байт-код, по крайней мере, для ограниченного количества Java-кода, который я написал до сих пор (хотя, по словам Хольгера, на это, по-видимому, нельзя полагаться).

0

В процессе сборки Eclipse регулярно проверяется на предмет соответствия: любые скомпилированные файлы классов из проектов, которые не имеют изменений в git с момента последней базовой линии, имеют любую двоичную разницу по сравнению с файлом jar из этой базовой линии. Опыт говорит о том, что действительно различия происходят только тогда, когда в компиляторе были сделаны соответствующие изменения.

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

В этом случае компилятор является ecj.

См. recent example logfile от компаратора (скоро будет удален), что привело к неожиданным изменениям файла класса, которые затем были отслежены до изменения конкретного компилятора. Ожидается, что соответствующие logs of a release будут пустыми.