Angabe der Java-Version in Maven - Unterschiede zwischen Eigenschaften und Compiler-Plugin

178

Ich bin nicht sehr erfahren mit Maven und während ich mit einem Projekt mit mehreren Modulen experimentierte, fragte ich mich, wie ich die Java-Version für alle meine untergeordneten Module in übergeordnetem Maven Pom angeben kann. Bis heute habe ich nur verwendet:

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

Bei der Recherche stellte ich jedoch fest, dass Sie die Java-Version auch im Maven-Compiler-Plugin wie folgt angeben können:

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

Und wickeln Sie dies dann in das Plugin-Management-Tag ein, um die Verwendung dieses Poms durch Kinder zu ermöglichen. Die erste Frage ist also, was sind die Unterschiede zwischen dem Festlegen der Java-Version in den Eigenschaften und im Maven-Compiler-Plugin?

Ich konnte keine klare Antwort finden, aber während der Recherche stellte ich fest, dass Sie die Java-Version auch folgendermaßen angeben können:

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

was darauf hindeutet, dass das Compiler-Plugin vorhanden ist, auch wenn ich es nicht explizit deklariere. Ausführen von MVN-Paketausgaben mit

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

und einige andere Plugins, die ich nicht deklariert habe. Sind diese Plugins standardmäßig ein versteckter Teil von Maven Pom? Gibt es Unterschiede zwischen der Einstellung von Quelle / Ziel in den Eigenschaften und im Konfigurationselement des Maven-Plugins?

Einige andere Fragen sind - welcher Weg sollte verwendet werden (und wann, wenn sie nicht gleich sind)? Welches ist am besten für Projekte mit mehreren Modulen geeignet und was passiert, wenn sich die in pom angegebene Java-Version von der in JAVA_HOME angegebenen Version unterscheidet?

Plebejusz
quelle

Antworten:

288

Wie gebe ich die JDK-Version an?

1) <java.version>wird in der Maven-Dokumentation nicht erwähnt.
Es ist eine Spring Boot-Spezifität.
Es ermöglicht das Festlegen der Quell- und der Ziel-Java-Version mit derselben Version wie dieser, um Java 1.8 für beide anzugeben:

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

Fühlen Sie sich frei, es zu verwenden, wenn Sie Spring Boot verwenden.

2) Verwenden von maven-compiler-pluginoder maven.compiler.source/ maven.compiler.targetEigenschaften, um die sourceund die targetsind äquivalent.

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

und

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

sind gemäß der Maven-Dokumentation des Compiler-Plugins äquivalent, da die <source>und die <target>Elemente in der Compilerkonfiguration die Eigenschaften verwenden maven.compiler.sourceund maven.compiler.targetob sie definiert sind.

Quelle

Das -sourceArgument für den Java-Compiler.
Der Standardwert ist : 1.6.
Benutzereigenschaft ist : maven.compiler.source.

Ziel

Das -targetArgument für den Java-Compiler.
Der Standardwert ist : 1.6.
Benutzereigenschaft ist : maven.compiler.target.

Informationen zu den Standardwerten für sourceund targetBeachten Sie, dass sich die Standardwerte seit dem 3.8.0Maven-Compiler von 1.5bis geändert haben1.6 .

3) Das Maven-Compiler-Plugin 3.6und spätere Versionen bieten einen neuen Weg:

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

Sie könnten auch nur erklären:

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

Derzeit funktioniert dies jedoch nicht, da die von maven-compiler-pluginIhnen verwendete Standardversion nicht auf einer ausreichend aktuellen Version basiert.

Das Maven- releaseArgument vermittelt release: eine neue JVM-Standardoption , die wir von Java 9 übergeben könnten:

Kompiliert gegen die öffentliche, unterstützte und dokumentierte API für eine bestimmte VM-Version.

Auf diese Weise bietet einen Standard - Weg , um die gleiche Version für den angeben source, die targetund die bootstrapJVM - Optionen.
Beachten Sie, dass die Angabe von bootstrapeine gute Vorgehensweise für Cross-Compilations ist und nicht schadet, wenn Sie auch keine Cross-Compilations durchführen.


Wie kann die JDK-Version am besten angegeben werden?

Der erste Weg ( <java.version>) ist nur zulässig, wenn Sie Spring Boot verwenden.

Für Java 8 und niedriger:

Zu den beiden anderen Möglichkeiten: Bewerten der maven.compiler.source/ maven.compiler.targetEigenschaften oder Verwenden der maven-compiler-plugin, können Sie die eine oder andere verwenden. An den Fakten ändert sich nichts, da die beiden Lösungen schließlich auf denselben Eigenschaften und demselben Mechanismus beruhen: dem Maven-Core-Compiler-Plugin.

Wenn Sie im Compiler-Plugin keine anderen Eigenschaften oder Verhaltensweisen als Java-Versionen angeben müssen, ist die Verwendung dieser Methode sinnvoller, da dies prägnanter ist:

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

Aus Java 9:

Das releaseArgument (dritter Punkt) ist eine Möglichkeit, stark zu überlegen, ob Sie dieselbe Version für die Quelle und das Ziel verwenden möchten.

Was passiert, wenn sich die Version zwischen dem JDK in JAVA_HOME und dem in der Datei pom.xml angegebenen unterscheidet?

Es ist kein Problem, wenn das JDK, auf das von verwiesen JAVA_HOMEwird, mit der im pom angegebenen Version kompatibel ist. Um jedoch eine bessere Kompatibilität zwischen Kompilierungen zu gewährleisten, sollten Sie die bootstrapJVM-Option mit dem Wert des Pfads rt.jarder targetVersion als Wert hinzufügen .

Es ist wichtig zu beachten, dass die sourceund die targetVersion in der Maven-Konfiguration der JDK-Version, auf die von verwiesen wird, nicht überlegen sein sollten JAVA_HOME.
Eine ältere Version des JDK kann nicht mit einer neueren Version kompiliert werden, da die Spezifikation nicht bekannt ist.

Informationen zu den unterstützten Quell-, Ziel- und Release-Versionen gemäß dem verwendeten JDK finden Sie unter Java-Kompilierung: Quell-, Ziel- und Release-unterstützte Versionen .


Wie wird der von JAVA_HOME referenzierte Fall von JDK behandelt, der nicht mit den im pom angegebenen Java-Ziel- und / oder Quellversionen kompatibel ist?

Wenn Sie beispielsweise JAVA_HOMEauf ein JDK 1.7 verweisen und in der Compilerkonfiguration Ihrer pom.xml ein JDK 1.8 als Quelle und Ziel angeben, ist dies ein Problem, da das JDK 1.7 wie erläutert nicht kompilieren kann .
Aus seiner Sicht ist es eine unbekannte JDK-Version, seit sie danach veröffentlicht wurde.
In diesem Fall sollten Sie das Maven-Compiler-Plugin so konfigurieren, dass das JDK folgendermaßen angegeben wird:

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

Weitere Details finden Sie in Beispielen mit dem Maven Compiler Plugin .


Es wird nicht gefragt, aber Fälle, in denen dies komplizierter sein kann, sind die Angabe der Quelle, aber nicht des Ziels. Je nach Quellversion wird möglicherweise eine andere Version im Ziel verwendet. Regeln sind besonders: Sie können sie im Teil Cross-Compilation Options lesen .


Warum wird das Compiler-Plugin bei der Ausführung des Maven- packageZiels in der Ausgabe verfolgt, auch wenn Sie es nicht in der Datei pom.xml angeben?

Um Ihren Code zu kompilieren und allgemeiner alle für ein Maven-Ziel erforderlichen Aufgaben auszuführen, benötigt Maven Tools. So nutzt es Kern Maven Plugins (Sie einen Core Maven Plugin erkennt durch seine groupId: org.apache.maven.plugins) die erforderlichen Aufgaben zu tun: Compiler - Plugin für die Erstellung von Klassen, Test - Plugin zum Ausführen von Tests, und so für ... Also, auch wenn Sie dies nicht tun Deklarieren Sie diese Plugins, sie sind an die Ausführung des Maven-Lebenszyklus gebunden.
Im Stammverzeichnis Ihres Maven-Projekts können Sie den folgenden Befehl ausführen: mvn help:effective-pomum den endgültigen POM effektiv zu nutzen. Sie können unter anderem angehängte Plugins von Maven (angegeben oder nicht in Ihrer pom.xml angegeben) mit der verwendeten Version, ihrer Konfiguration und den ausgeführten Zielen für jede Phase des Lebenszyklus anzeigen.

In der Ausgabe des mvn help:effective-pomBefehls sehen Sie die Deklaration dieser Kern-Plugins im <build><plugins>Element, zum Beispiel:

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

Weitere Informationen hierzu finden Sie in der Einführung zum Maven-Lebenszyklus in der Maven-Dokumentation .

Sie können diese Plugins jedoch deklarieren, wenn Sie sie mit anderen Werten als Standardwerte konfigurieren möchten (z. B. wenn Sie das Maven-Compiler-Plugin in Ihrer pom.xml deklariert haben, um die zu verwendende JDK-Version anzupassen) oder wenn Sie Ich möchte einige Plugin-Ausführungen hinzufügen, die im Maven-Lebenszyklus nicht standardmäßig verwendet werden.

davidxxx
quelle
Vielen Dank für die ausführliche Erklärung, jetzt ist es mir viel klarer. Auch über <java.version> - Ich habe dies in einem Code-Snippet gesehen, vielleicht war das eine benutzerdefinierte Eigenschaft, und ich habe fälschlicherweise angenommen, dass es die Art ist, die Java-Version zu deklarieren, die <maven.compiler.x>von nun an bei der Eigenschaft bleibt .
Plebejusz
Gern geschehen, mit Vergnügen :) Anfangs war es nicht meine Absicht, so viel zu entwickeln, aber als ich anfing, konnte ich nicht aufhören :) Für `<java.version>` ist es sehr wahrscheinlich. Wir sehen uns und guter Maven!
Davidxxx
1
" Es ist kein Problem, wenn das JDK Ihres JAVA_HOME mit den angegebenen Versionen im POM kompatibel ist. " Dies ist nicht (notwendigerweise) der Fall. Überprüfen Sie diesen
Stapelüberlauf-
2
@ Robin A. Meade danke für das Feedback. Ich benutze Spring Boot, aber ich wusste es nicht. Persönlich fand ich es nicht standardmäßig genug, um verwendet oder als etwas verwendet zu werden, das verwendet werden soll. Spring Boot bietet einige sehr interessante Dinge, aber in einigen Fällen sind seine Funktionen sehr erkennbar. Das Überschreiben des Namens einer Standard-Maven-Eigenschaft, um nicht sowohl das Quell- als auch das Ziel-JDK zu füllen, erscheint als schlechte Idee, da es für eine Anwendung einmal ausgeführt wird. Sie verlieren den Standard, um eine einfache XML-Zeile in Ihrer Anwendung zu sparen. Woah! Was für eine Idee ...
davidxxx
1
@ MasterJoe2 Sie finden es in der offiziellen Javac-Dokumentation der Version 10: docs.oracle.com/javase/10/tools/javac.htm#JSWOR627 . Ich hatte diese Antwort in zwei Teile geteilt, da sie zu groß wird. Sie können sich das auch ansehen: stackoverflow.com/questions/51692748/…
davidxxx
3

Keine der oben genannten Lösungen hat sofort für mich funktioniert. Also habe ich folgendes gemacht: -

  1. Hinzugefügt

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

    in pom.xml

  2. Ging zum Project Properties > Java Build Path, entfernte dann die JRE- Systembibliothek, auf die verwiesen wurde JRE1.5.

  3. Force hat das Projekt aktualisiert.

Sen.
quelle
Welche Version geben Sie für Java 10 und höher an? Ist es 10 oder 1,10?
MasterJoe2
@ MasterJoe2 von Java 9 und höheren Versionen müssen Sie die Versionsnummer so schreiben, wie sie ist (<Version> 10 </ Version>), und für die folgenden Versionen müssen Sie 1. vor der Version (<Version>) hinzufügen 1.5 </ version>)
ikbel benab
0

Betrachten Sie die Alternative:

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

Es sollte dasselbe sein, maven.compiler.source/maven.compiler.targetaber die obige Lösung funktioniert für mich, andernfalls erhält die zweite die übergeordnete Spezifikation (ich habe eine Matrioska von .pom).

Stefano
quelle