Гипотетический сценарий:
У меня есть проект, исходный уровень соответствия которого указан к 1,5. Теперь я компилирую этот проект с двумя различными JDKs: Сначала с Обновлением JDK 6 7 и затем с Обновлением JDK 6 20.
Эти два различных JDKs производят другой байт-код Java, хотя они только отличаются по своей Версии обновления?
Сгенерированный код обычно отличается только в случае исправления ошибок компилятора.
Однако JLS не определяет соответствие 1:1 между исходным кодом и сгенерированным байт-кодом, поэтому не следует полагаться на то, что будет сгенерирован точно такой же байт-код.
Ответим на этот вопрос с другой стороны: нет никакой гарантии, что две версии jdk производят идентичный байт-код. Поэтому в целом можно ожидать различий.
Нет ничего, что могло бы помешать разным версиям генерировать разные байткоды, пока это соответствует поведению, указанному в JLS. JLS оставляет многие детали реализации варьироваться от одной реализации к другой.
С какой стати кто-то будет заниматься выпуском обновления комплекта разработки, если это не приведет к изменению байт-кода хотя бы в некоторых случаях? Я сильно сомневаюсь, что кто-то будет делать это только для обновления документации.
Байткод может немного отличаться, но это не повод для беспокойства, поскольку он все равно будет совместим.
То, что действительно будет выполнено, зависит от JIT.
Компилятор, например, JDK 6 Обновление 7 может выводить немного другой байт-код, чем компилятор JDK 6 Update 20, но, поскольку это оба Java 6, файлы классов будут полностью совместимы - вы сможете без проблем запускать код, скомпилированный с обновлением 20, в обновлении 7.
Между основными версиями Java (например, Java 5 и Java 6) могут быть изменения, поэтому код, скомпилированный в более новой версии, не будет работать в более старой версии. Например, для Java 7, скорее всего, будет новая инструкция invokedynamic . Файлы классов, содержащие эту инструкцию, не будут работать в более старых версиях Java.
Однако такие большие изменения между версиями обновлений никогда не делаются.
Как обычно бывает для разных компиляторов, это также и в случае Java: результат должен быть одинаковым, но способ его достижения может быть (с точки зрения байт-кода) другим., Например из-за оптимизации или чего-то подобного. JVM - это V-машина на основе стека; Ниже приводится воображаемый пример (я не знаю мнемоники jvm для кодов операций инструкций)
push 10 push 20 add
push 19 push 1 add push 10 add
Они дают тот же результат, но сгенерированные байткоды отличаются (первый слегка оптимизирован, второй "полностью" не оптимизирован; третий вариант может быть push 30
, поскольку мы добавляем известные (вероятно, во время компиляции) константы). Это простой случай, но можно легко построить более сложный.
Если вы компилируете с разными версиями JDK, я бы посоветовал использовать параметр target для javac. В противном случае вы не сможете запустить jar со старым JDK.
Вы также можете использовать параметр source для javac, чтобы убедиться, что разработчик не использует классы / методы, добавленные в более позднюю версию JDK.