Вказання версії 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, вказана у пам’яті, відрізняється від версії, вказаної в JAVA_HOME?

Відповіді:


289

Як вказати версію JDK?

1) <java.version>не посилається на документацію Maven.
Це специфіка весняного завантаження.
Це дозволяє встановити вихідну та цільову версію 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-компілятор 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 для певної версії VM.

Цей спосіб забезпечує стандартний спосіб вказати ту саму версію для параметрів source, targetта bootstrapJVM.
Зауважте, що вказати значення 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сумісний з версією , зазначеної в ПОМ , а для забезпечення кращої сумісності крос-компіляції думати про додавання bootstrapопції JVM з в якості значення стезю rt.jarв targetверсії.

Важливо врахувати, що версія sourceта targetверсія в конфігурації Maven не повинні перевершувати версію JDK, на яку посилається JAVA_HOME.
Старіша версія JDK не може компілюватись із більш новою версією, оскільки не знає її специфікації.

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


Як поводитись із випадком JDK, на який посилається JAVA_HOME, не сумісний із цільовою версією Java та / або вихідними версіями, вказаними у пам’яті?

Наприклад, якщо ви 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ефективно використовувати остаточну пом. Ви можете побачити серед іншої інформації додані додатки 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-компілятора у своєму pom.xml для налаштування версії JDK для використання) або коли ви хочемо додати кілька виконань плагінів, які не використовуються за замовчуванням у життєвому циклі Maven.


Дякую за широке пояснення, зараз мені це набагато зрозуміліше. Також про <java.version> - Я бачив це в якомусь фрагменті коду, можливо, це було якесь власне властивість, і я помилково припустив, що це спосіб оголошення версії java, відтепер буде дотримуватися <maven.compiler.x>властивості.
Plebejusz

Запрошуємо вас із задоволенням :) Спочатку я не мав намір так сильно розвиватися, але коли я почав, я не міг зупинитися :) Для `<java.version>` це дуже ймовірно. Побачимось і добрий мав!
davidxxx

1
« Це не проблема , якщо JDK вашого JAVA_HOME поєднає з зазначеними версіями в П » це не (necessarely) вірно, перевірте це переповнення стеки потік для довідки
A_Di-Маттео

2
@Robin A. Meade дякую за відгук. Я використовую весняний черевик, але я цього не знав. Особисто я не вважаю, що це досить стандартно, щоб його використовувати або посилатись як щось, що потрібно використовувати. Весняний черевик пропонує дуже цікаві речі, але в деяких випадках його особливості є дуже дискусійними. Перезапис імені стандартного властивості 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. Force оновив проект.


Яку версію ви вказуєте для Java 10 і вище? Це 10 чи 1,10?
MasterJoe2

@ MasterJoe2 з версій java 9 і вище вам потрібно написати номер версії такою, якою вона є (<version> 10 </version>), а для наведених нижче версій ви повинні додати 1. перед версією (<version> 1.5 </version>)
ikbel benab

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)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.