Компиляция в более старые версии Java с использованием Maven

#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 просто неверно.