Указание версии Java в Maven - различия между свойствами и плагином компилятора

178

Я не очень разбираюсь в 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?

Plebejusz
источник

Ответы:

289

Как указать версию 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умолчанию версия не использует достаточно свежую версию.

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

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

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


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

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

Для Java 8 и ниже:

О двух других способах: оценивая maven.compiler.source/ maven.compiler.targetproperties или используя 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совместим с версией , указанной в ПОМ , а для обеспечения лучшей совместимости кросс-компиляции думать о добавлении bootstrapопции JVM с в качестве значения стезю rt.jarв targetверсии.

Важно учитывать, что версия sourceand 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, даже если вы не указали его в 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.

davidxxx
источник
Спасибо за подробное объяснение, теперь мне стало намного понятнее. Также о <java.version> - я видел это в некотором фрагменте кода, может быть, это было какое-то пользовательское свойство, и я ошибочно предположил, что это способ объявить версию Java, теперь будет придерживаться <maven.compiler.x>свойства.
Плебеюш
Добро пожаловать, с удовольствием :) Изначально я не собирался так сильно развиваться, но когда я начал, я не мог остановиться :) Для `<java.version>` это очень вероятно. Увидимся и хорошие Maven!
davidxxx
1
« Это не проблема, если JDK вашего JAVA_HOME совместим с указанными версиями в pom », это не является (обязательно) истиной, проверьте этот поток переполнения стека для справки
A_Di-Matteo
2
@Robin A. Мид, спасибо за отзыв. Я использую весенний ботинок, но я этого не знал. Лично я не нашел это достаточно стандартным, чтобы использовать или ссылаться на него как на что-то, что можно использовать. Весенняя загрузка предлагает некоторые очень интересные вещи, но в некоторых случаях его особенности очень сомнительны. Переопределение имени стандартного свойства maven для того, чтобы не заполнять как исходный, так и целевой jdk, выглядит действительно плохой идеей, поскольку оно выполняется один раз для приложения. Вы теряете стандарт, чтобы сэкономить простую строку XML в вашем приложении. Вау! Что за идея ...
davidxxx
1
@ MasterJoe2 Вы найдете его в официальной документации javac версии 10: docs.oracle.com/javase/10/tools/javac.htm#JSWOR627 . Я разделил этот ответ на две части, так как он становится слишком большим, вы также можете посмотреть на это: stackoverflow.com/questions/51692748/…
davidxxx
3

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

  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, затем удалил Системную Библиотеку JRE, которая указывала на JRE1.5.

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

сен
источник
Какую версию вы указываете для Java 10 и выше? Это 10 или 1,10?
MasterJoe2
@ MasterJoe2 из java 9 и более поздних версий, вам нужно написать номер версии в том виде, как он есть (<версия> 10 </ версия>), а для следующих версий вы должны добавить 1. перед версией (<версия> 1.5 </ version>)
Икбель Бенаб,
0

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

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

Стефано
источник