Что такое флаг --release в компиляторе Java 9?

89

В 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?

ЖекаКозлов
источник

Ответы:

113

Не совсем.

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-интерфейсов платформы старых выпусков, упомянутыми в разделе «Риски и предположения». Это означает, что для работы кросс-компиляции вам не нужна более старая версия, установленная на вашем компьютере.

Эндрю Ли
источник
одно сомнение, можно ли использовать функции из jdk 9-11 в коде, и он все еще работает на java runtime 8?
Cristiano
Нет, их не будет в двоичном
Rogue
Что вы думаете о "Platform API"? Есть что-то на уровне байт-кода? или что-то связанное с базовой платформой x86 или API ОС?
Хосе Сифуэнтес
2
@JoseCifuentes, «Platform API» здесь предоставляется JDK API, его версия без --releaseфлага будет выведена из JDK, используемого для компиляции, который обычно отличается от JDK, на который вы нацеливаетесь с помощью -sourceи -target. Это может вас укусить, если вы используете классы / методы, представленные никогда не в JDK, а в том, который вы нацеливаете. Это очень тонко, если компилятор выбирает перегрузку метода, которая была добавлена ​​в более поздней версии, а не на предыдущую, которую вы планировали, тем самым незаметно нарушая двоичную совместимость.
Оливер Гонджа
30

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

ЖекаКозлов
источник