В Java 9 javac
появился новый флаг --release
:
> javac --help
...
--release <release>
Compile for a specific VM version. Supported targets: 6, 7, 8, 9
Чем он отличается от -source
и -target
флаги? Это просто ярлык -source X -target X
?
В Java 9 javac
появился новый флаг --release
:
> javac --help
...
--release <release>
Compile for a specific VM version. Supported targets: 6, 7, 8, 9
Чем он отличается от -source
и -target
флаги? Это просто ярлык -source X -target X
?
Ответы:
Не совсем.
JEP 247: Compile for Older Platform Versions определяет этот новый параметр командной строки--release
:
Мы определили новую опцию командной строки
--release
, которая автоматически настраивает компилятор для создания файлов классов, которые будут связываться с реализацией данной версии платформы. Для платформ, предопределенных вjavac
,--release N
эквивалентно-source N -target N -bootclasspath <bootclasspath-from-N>
. (курсив мой)
Так что нет, это не эквивалент -source N -target N
. Причина добавления указана в разделе «Мотивация»:
javac
предоставляет два параметра командной строки-source
и-target
, которые могут использоваться для выбора версии языка Java, принимаемой компилятором, и версии создаваемых им файлов классов соответственно. Однако по умолчаниюjavac
компилируется с использованием самой последней версии API платформы. Поэтому скомпилированная программа может случайно использовать API-интерфейсы, доступные только в текущей версии платформы. Такие программы не могут работать на старых версиях платформы, независимо от значений, переданных в-source
и-target
. параметры. Это долгосрочная проблема удобства использования, поскольку пользователи ожидают, что, используя эти параметры, они получат файлы классов, которые могут работать на указанной версии платформы.
Короче говоря, для кросс-компиляции недостаточно указать параметры источника и цели. Поскольку javac
по умолчанию они компилируются с использованием самых последних API-интерфейсов платформы, их нельзя гарантировать для работы в более старых версиях. Вам также необходимо указать -bootclasspath
параметр, соответствующий более старой версии, для правильной кросс-компиляции. Это будет включать правильную версию API для компиляции и выполнение в более старой версии. Поскольку об этом очень часто забывали, было решено добавить один параметр командной строки, который делал все необходимое для правильной кросс-компиляции.
Дополнительное чтение в списке рассылки и Oracle Docs . Первоначальная ошибка была зарегистрирована здесь . Обратите внимание, что после интеграции этой опции сборки JDK поставляются в комплекте с описаниями API-интерфейсов платформы старых выпусков, упомянутыми в разделе «Риски и предположения». Это означает, что для работы кросс-компиляции вам не нужна более старая версия, установленная на вашем компьютере.
--release
флага будет выведена из JDK, используемого для компиляции, который обычно отличается от JDK, на который вы нацеливаетесь с помощью -source
и -target
. Это может вас укусить, если вы используете классы / методы, представленные никогда не в JDK, а в том, который вы нацеливаете. Это очень тонко, если компилятор выбирает перегрузку метода, которая была добавлена в более поздней версии, а не на предыдущую, которую вы планировали, тем самым незаметно нарушая двоичную совместимость.
--release X
больше , чем просто ярлык , -source X -target X
потому что -source
и -target
не являются достаточными , чтобы безопасно компилировать старую версию. Вам также необходимо установить -bootclasspath
флаг, который должен соответствовать более раннему выпуску (и этот флаг часто забывают). Таким образом, в Java-они сделали один --release
флаг , который является заменой для трех флагов: -source
, -target
и -bootclasspath
.
Итак, это пример компиляции в Java 1.7:
javac --release 7 <source files>
Обратите внимание, что вам даже не нужно устанавливать JDK 7 на вашем компьютере. JDK 9 уже содержит необходимую информацию, чтобы предотвратить случайную привязку к символам, которых не было в JDK 7.