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