#java #maven
Вопрос:
Мой код написан на Java 17. Мне было интересно, есть ли способ скомпилировать более старые версии Java (8 и более поздние).
Многие люди в Интернете предполагают, что я должен использовать что-то вроде этого:
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
Однако, когда я это делаю, я получаю следующую проблему:
Caused by: java.lang.IllegalStateException: warning: source release 17 requires target release 17
Использование release
с maven-compiler-plugin вместо этого также не помогло.
Чего я не понимаю, так это того, что если цель и источник должны быть точно такими же, то зачем нам нужны оба события?
Кстати, я использую Maven 3.8.3.
Комментарии:
1. Простой ответ на этот вопрос. Это невозможно. Это основано на использовании функций JDK17 (закрытые классы, текстовые блоки, переменные и т. Д.), Которых нет в JDK8…
Ответ №1:
Ваши ожидания от JDK неверны в отношении совместимости с компилятором. Компилятор не совместим с прямой, он обратно совместим. Поэтому в вашем случае установка компилятора target
на Java 1.8 с source
использованием Java 17 не будет работать.
В Java 17 есть новые функции, которые несовместимы с Java 1.8, и поэтому Java JDK 1.8 не поймет, что это такое, и обязательно выдаст синтаксические ошибки. Это объясняет предупреждение, которое вы получаете от плагина компилятора Maven.
В то же время Java 17 слишком далеко впереди. Хотя он будет понимать весь синтаксис, присутствующий в предыдущих версиях Java, вы столкнетесь с ошибками во время компиляции из-за отсутствия классов. Примером такой ошибки является java.lang.NoClassDefFoundError
или java.lang.ClassNotFoundException
поскольку некоторые классы устарели и были удалены.
Начиная с Java 9, Java решила поддерживать не более трех версий. Поэтому, если вы работаете с Java 17, последней поддержкой будет Java 14. В этом случае, если вы напишете весь код, совместимый с JDK 14, и скомпилируете с JDK 17, он продолжит работать для всех промежуточных версий.
Это похоже на то, как это всегда было с Java 1.8 и ниже. Код должен быть совместим с вашей целевой средой. Итак, если у вас targetCompatibility
Java 1.8, то у sourceCompatibility
вас также должна быть Java 1.8 и ниже.
Пример:
<!-- Correct -->
<properties>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!-- Wrong -->
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
Комментарии:
1. Спасибо за объяснение! Я действительно смешал их в своей голове. Спасибо за разъяснение
2. Я нашел упоминание о политике «один три назад» для поддерживаемых исходных и целевых параметров в этом проекте (не доработан) JEP 182: Политика удаления javac -source и -target Options . Но я не смог найти никакого официального заявления о политике. Можете ли вы привести ссылку для записи? (Кроме того, очень хороший ответ.)
3. Если вы хотите скомпилировать свой исходный код в JDK8, вы должны использовать
<maven.compiler.release>8</maven.compiler.release>
(JDK9 ) Вместо source / target и т. Д. … Это сохранит созданный файл класса совместимым с JDk8… Это самый простой способ сделать это…4. @khmarbaise я упомянул в вопросе, который
release
не сработал5. @khmarbaise ну, в этом случае это не будет иметь значения, потому что я хотел написать код на Java 17 и иметь возможность скомпилировать его в более старую версию, благодаря которой я узнал, что я неправильно понял обратную / прямую совместимость.
Ответ №2:
Не всегда бывает так, что вы не можете скомпилировать с понижающей совместимостью. Однако, так же, как в версии 1.8 были введены лямбды, которые невозможно было сделать совместимыми с средами выполнения до версии 1.8, 17 включает новые функции (в частности, закрытые классы), которые старые среды выполнения не могут понять. Если вы хотите сообщить компилятору: «Я не буду использовать эти функции, чтобы вы могли быть совместимы», вы устанавливаете выпуск вашего компилятора на более старую версию.
Комментарии:
1. Но разве это не должно вызывать какое-то исключение, говорящее «Я не знаю, что это такое»? Ошибка, которой я поделился, просто говорит, что они должны быть одинаковыми, и это основная причина исключения, которое я получаю
2. @MansurGulami Нет, в нем говорится, что исходная версия 17 конкретно не совместима с предыдущими версиями и что вам нужно изменить ту или иную.
3. Я действительно пробовал разные комбинации. Например, source: 11, target 8 также выдает мне точно такую же ошибку. Я чувствую, что в Maven обе эти вещи должны быть одинаковыми.
4. @MansurGulami просто неверно.