Задание java-версии в maven - различия между свойствами и плагином компилятора

Я не очень опытен с maven и, экспериментируя с многомодульным проектом, я начал задаваться вопросом, как я могу указать java-версию для всех моих дочерних модулей в родительском maven pom. До сегодняшнего дня я использовал только:

<properties>
    <java.version>1.8</java.version>
</properties>

но при исследовании я обнаружил, что вы также можете указать java-версию в плагине компилятора maven, например:

<plugins>
    <plugin>    
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

И затем оберните это в тег управления плагином, чтобы использовать это использование детьми. Итак, первый вопрос: каковы различия в настройке java-версии в свойствах и в плагине компилятора maven?

Я не мог найти четкого ответа, но в процессе исследования я обнаружил, что вы также можете указать версию java следующим образом:

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

которые предполагают, что плагин компилятора существует, даже если я не объявляю его явно. Выполнение выходов пакета mvn с помощью

maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---

и некоторые другие плагины, которые я не объявлял. Значит, эти плагины по умолчанию, скрытая часть maven pom? Существуют ли различия в настройке источника/цели в свойствах и в элементе конфигурации плагина maven?

Некоторые другие вопросы - каким образом следует использовать (и если они не равны)? Какой из них лучше всего подходит для многомодульного проекта, и что произойдет, если версия java, указанная в pom, отличается от версии, указанной в JAVA_HOME?

Ответ 1

Как указать версию JDK?

1) <java.version> не упоминается в документации Maven.
Это специфика Spring Boot.
Это позволяет установить исходную и целевую версии Java с одной и той же версией, такой как эта, чтобы указать java 1.8 для обоих:

<properties>
     <java.version>1.8</java.version>
</properties>   

Не стесняйтесь использовать его, если вы используете Spring Boot.

2) Использование свойств maven-compiler-plugin или maven.compiler.source/maven.compiler.target для указания source и target эквивалентны.

<plugins>
    <plugin>    
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <source>1.8</source>
            <target>1.8</target>
        </configuration>
    </plugin>
</plugins>

а также

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

эквивалентны в соответствии с документацией Maven плагина компилятора, поскольку элементы <source> и <target> в конфигурации компилятора используют свойства maven.compiler.source и maven.compiler.target если они определены.

источник

-source для компилятора Java.
Значение по умолчанию: 1.6.
Свойство пользователя: maven.compiler.source.

цель

-target для компилятора Java.
Значение по умолчанию: 1.6.
Свойство пользователя: maven.compiler.target.

Что касается значений по умолчанию для source и target, обратите внимание, что начиная с версии 3.8.0 компилятора maven, значения по умолчанию изменились с 1.5 до 1.6.

3) Maven-compiler-plugin 3.6 и более поздние версии предоставляют новый способ:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <release>9</release>
    </configuration>
</plugin>

Вы также можете объявить просто:

<properties>
    <maven.compiler.release>9</maven.compiler.release>
</properties>

Но в настоящее время он не будет работать, так как используемая по умолчанию версия maven-compiler-plugin не использует достаточно свежую версию.

Maven release аргумент передает release: а новый стандарт JVM вариант, который мы могли бы перейти от Java 9:

Компилируется с общедоступным, поддерживаемым и документированным API для конкретной версии виртуальной машины.

Этот способ предоставляет стандартный способ указать одну и ту же версию для source, target и параметров bootstrap JVM.
Обратите внимание, что указание bootstrap является хорошей практикой для кросс-компиляции, и это не повредит, если вы не сделаете кросс-компиляцию.


Какой лучший способ указать версию JDK?

Первый способ (<java.version>) разрешен, только если вы используете Spring Boot.

Для Java 8 и ниже:

О двух других способах: оценивая свойства maven.compiler.source/maven.compiler.target или используя maven-compiler-plugin, вы можете использовать один или другой. Это ничего не меняет в фактах, поскольку в конечном итоге оба решения опираются на одни и те же свойства и один и тот же механизм: плагин компилятора ядра maven.

Что ж, если вам не нужно указывать другие свойства или поведение, кроме версий Java, в плагине компилятора, использование этого способа имеет больше смысла, поскольку это более кратко:

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

Из Java 9:

Аргумент release (третий пункт) - это способ решительно рассмотреть, хотите ли вы использовать одну и ту же версию для источника и цели.

Что происходит, если версия отличается между JDK в JAVA_HOME и той, которая указана в pom.xml?

Это не проблема, если JDK, на который ссылается JAVA_HOME, совместим с версией, указанной в pom, но для обеспечения лучшей совместимости с кросс-компиляцией подумайте о добавлении опции bootstrap JVM со значением as пути к rt.jar target версия.

Важно учитывать, что source и target версии в конфигурации Maven не должны превосходить версию JDK, на которую ссылается JAVA_HOME.
Старая версия JDK не может быть скомпилирована с более новой версией, поскольку она не знает ее спецификации.

Чтобы получить информацию об исходной, целевой и выпускной поддерживаемых версиях в соответствии с используемым JDK, пожалуйста, обратитесь к компиляции Java: исходная, целевая и выпускная поддерживаемые версии.


Как обрабатывать случай JDK, на который ссылается JAVA_HOME, несовместим с целевой версией Java и/или исходными версиями, указанными в pom?

Например, если ваш JAVA_HOME ссылается на JDK 1.7 и вы указываете JDK 1.8 в качестве источника и цели в конфигурации компилятора вашего pom.xml, это будет проблемой, потому что, как объяснено, JDK 1.7 не знает, как скомпилировать с.
С его точки зрения, это неизвестная версия JDK, поскольку она была выпущена после нее.
В этом случае вы должны сконфигурировать плагин компилятора Maven, чтобы указать JDK следующим образом:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerVersion>1.8</compilerVersion>      
        <fork>true</fork>
        <executable>D:\jdk1.8\bin\javac</executable>                
    </configuration>
</plugin>

Вы могли бы иметь больше деталей в примерах с плагином компилятора maven.


Это не спрашивается, но случаи, когда это может быть более сложным, это когда вы указываете источник, но не цель. Он может использовать другую версию в соответствии с исходной версией. Особые правила: о них вы можете прочитать в разделе "Параметры кросс-компиляции".


Почему плагин компилятора прослеживается в выводе при выполнении цели package Maven package даже если вы не указали его в pom.xml?

Для компиляции вашего кода и в целом для выполнения всех задач, необходимых для достижения цели maven, Maven нужны инструменты. Таким образом, он использует основные плагины Maven (основной плагин Maven определяется по его groupId: org.apache.maven.plugins) для выполнения необходимых задач: плагин компилятора для компиляции классов, плагин тестирования для выполнения тестов и т.д. Для... Таким образом, даже если вы не объявляете эти плагины, они связаны с выполнением жизненного цикла Maven.
В корневом каталоге вашего проекта Maven вы можете запустить команду: mvn help:effective-pom чтобы эффективно использовать последний pom. Вы можете увидеть среди прочего информацию о подключенных плагинах Maven (указанных или не указанных в вашем pom.xml), с использованной версией, их конфигурацией и выполненными целями для каждой фазы жизненного цикла.

В выводе команды mvn help:effective-pom вы могли видеть объявление этих основных плагинов в элементе <build><plugins>, например:

...
<plugin>
   <artifactId>maven-clean-plugin</artifactId>
   <version>2.5</version>
   <executions>
     <execution>
       <id>default-clean</id>
       <phase>clean</phase>
       <goals>
         <goal>clean</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
 <plugin>
   <artifactId>maven-resources-plugin</artifactId>
   <version>2.6</version>
   <executions>
     <execution>
       <id>default-testResources</id>
       <phase>process-test-resources</phase>
       <goals>
         <goal>testResources</goal>
       </goals>
     </execution>
     <execution>
       <id>default-resources</id>
       <phase>process-resources</phase>
       <goals>
         <goal>resources</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
 <plugin>
   <artifactId>maven-compiler-plugin</artifactId>
   <version>3.1</version>
   <executions>
     <execution>
       <id>default-compile</id>
       <phase>compile</phase>
       <goals>
         <goal>compile</goal>
       </goals>
     </execution>
     <execution>
       <id>default-testCompile</id>
       <phase>test-compile</phase>
       <goals>
         <goal>testCompile</goal>
       </goals>
     </execution>
   </executions>
 </plugin>
  ...

Вы можете получить больше информации об этом во введении жизненного цикла Maven в документацию Maven.

Тем не менее, вы можете объявить эти плагины, когда хотите настроить их с другими значениями в качестве значений по умолчанию (например, вы сделали это, когда объявили плагин maven-compiler в вашем pom.xml, чтобы настроить используемую версию JDK) или когда вы хочу добавить некоторые исполнения плагинов, не используемые по умолчанию в жизненном цикле Maven.

Ответ 2

Ни одно из вышеперечисленных решений не сработало для меня сразу. Итак, я сделал следующее:

  1. добавленной

    <properties> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties>

    в pom.xml

  2. Перешел к " Project Properties > Java Build Path, затем удалил JRE1.5 библиотеку JRE, которая указывала на JRE1.5.

  3. Принудительно обновил проект.

Ответ 3

Рассмотрим альтернативу:

<properties>
    <javac.src.version>1.8</javac.src.version>
    <javac.target.version>1.8</javac.target.version>
</properties>

Это должно быть то же самое, что и для maven.compiler.source/maven.compiler.target но вышеупомянутое решение работает для меня, в противном случае второе получает родительскую спецификацию (у меня матриоска из .pom)