Specifica della versione java in maven - differenze tra proprietà e plugin del compilatore


178

Non ho molta esperienza con Maven e durante la sperimentazione di un progetto multi-modulo ho iniziato a chiedermi come posso specificare la versione Java per tutti i miei moduli figlio in padre Maven Pom. Fino ad oggi stavo usando solo:

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

ma durante la ricerca ho scoperto che puoi anche specificare la versione java nel plugin del compilatore di Maven, in questo modo:

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

E quindi avvolgilo nel tag di gestione dei plug-in per abilitare l'utilizzo da parte di poms figlio. Quindi la prima domanda è: quali sono le differenze tra l'impostazione della versione Java nelle proprietà e nel plugin del compilatore Maven?

Non sono riuscito a trovare una risposta chiara, ma durante la ricerca ho scoperto che puoi anche specificare la versione java in questo modo:

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

il che suggerisce che il plugin del compilatore è lì anche se non lo dichiaro esplicito. Esecuzione degli output del pacchetto mvn con

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

e alcuni altri plugin che non ho dichiarato. Quindi quei plugin sono predefiniti, parte nascosta di Maven Pom? Ci sono differenze tra l'impostazione dell'origine / destinazione nelle proprietà e nell'elemento di configurazione del plugin maven?

Alcune altre domande sono: quale modo dovrebbe essere usato (e quando se non sono uguali)? Quale è il migliore per il progetto multi-modulo e cosa succede se la versione java specificata in pom è diversa dalla versione indicata in JAVA_HOME?

Risposte:


289

Come specificare la versione JDK?

1) <java.version>non è indicato nella documentazione di Maven.
È una specificità di Spring Boot.
Permette di impostare la versione java di origine e destinazione con la stessa versione come questa per specificare java 1.8 per entrambi:

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

Sentiti libero di usarlo se usi Spring Boot.

2) Usare maven-compiler-plugino maven.compiler.source/ maven.compiler.targetproperties per specificare sourcee e targetsono equivalenti.

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

e

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

sono equivalenti secondo la documentazione Maven del plug-in del compilatore poiché <source>gli <target>elementi e nella configurazione del compilatore usano le proprietà maven.compiler.sourcee maven.compiler.targetse sono definiti.

fonte

L' -sourceargomento per il compilatore Java.
Il valore di default è: 1.6.
Proprietà utente è: maven.compiler.source.

bersaglio

L' -targetargomento per il compilatore Java.
Il valore di default è: 1.6.
Proprietà utente è: maven.compiler.target.

Informazioni sui valori predefiniti per sourcee target, si noti che dal 3.8.0compilatore del maven, i valori predefiniti sono cambiati da 1.5a1.6 .

3) Maven-compilatore-plugin 3.6e versioni successive forniscono un nuovo modo:

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

Puoi anche dichiarare solo:

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

Ma in questo momento non funzionerà poiché la maven-compiler-pluginversione predefinita che usi non si basa su una versione abbastanza recente.

L' releaseargomento Maven trasmette release: una nuova opzione standard JVM che potremmo passare da Java 9:

Compila contro l'API pubblica, supportata e documentata per una versione specifica della VM.

In questo modo viene fornito un modo standard per specificare la stessa versione per le opzioni source, the targete bootstrapJVM.
Si noti che specificare bootstrapè una buona pratica per compilazioni incrociate e non farà male se non si effettuano compilazioni incrociate.


Qual è il modo migliore per specificare la versione JDK?

Il primo modo ( <java.version>) è consentito solo se si utilizza Spring Boot.

Per Java 8 e versioni precedenti:

Per gli altri due modi: valutando le proprietà maven.compiler.source/ o usando , puoi usare l'una o l'altra. Non cambia nulla nei fatti poiché alla fine le due soluzioni si basano sulle stesse proprietà e sullo stesso meccanismo: il plug-in del compilatore core maven. maven.compiler.targetmaven-compiler-plugin

Bene, se non è necessario specificare altre proprietà o comportamenti rispetto alle versioni Java nel plug-in del compilatore, l'utilizzo in questo modo ha più senso in quanto è più conciso:

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

Da Java 9:

L' releaseargomento (terzo punto) è un modo di considerare fortemente se si desidera utilizzare la stessa versione per l'origine e la destinazione.

Cosa succede se la versione differisce tra il JDK in JAVA_HOME e quello specificato in pom.xml?

Non è un problema se il JDK riferimento la JAVA_HOMEè compatibile con la versione specificata nel pom ma per garantire una migliore compatibilità cross-compilazione pensare aggiungendo l' bootstrapopzione JVM con come valore il percorso della rt.jardella targetversione.

Una cosa importante da considerare è che la sourcee la targetversione nella configurazione di Maven non deve essere superiore alla versione JDK riferimento il JAVA_HOME.
Una versione precedente di JDK non può essere compilata con una versione più recente poiché non conosce le sue specifiche.

Per ottenere informazioni sull'origine, destinazione e rilascio delle versioni supportate in base al JDK utilizzato, fare riferimento alla compilazione java: origine, destinazione e rilascio versioni supportate .


In che modo gestire il caso di JDK a cui fa riferimento JAVA_HOME non è compatibile con la destinazione java e / o le versioni di origine specificate nel pom?

Ad esempio, se si JAVA_HOMEfa riferimento a un JDK 1.7 e si specifica un JDK 1.8 come sorgente e destinazione nella configurazione del compilatore di pom.xml, sarà un problema perché, come spiegato, il JDK 1.7 non sa come compilare .
Dal suo punto di vista, è una versione JDK sconosciuta da quando è stata rilasciata dopo di essa.
In questo caso, è necessario configurare il plug-in del compilatore Maven per specificare il JDK in questo modo:

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

Potresti avere maggiori dettagli negli esempi con il plugin del compilatore di Maven .


Non viene richiesto, ma i casi in cui ciò può essere più complicato è quando si specifica l'origine ma non il target. Potrebbe utilizzare una versione diversa nella destinazione in base alla versione di origine. Le regole sono particolari: puoi leggerne nella sezione Opzioni di compilazione incrociata .


Perché il plug-in del compilatore viene tracciato nell'output durante l'esecuzione packagedell'obiettivo Maven anche se non lo si specifica in pom.xml?

Per compilare il codice e più in generale per eseguire tutte le attività necessarie per un obiettivo maven, Maven ha bisogno di strumenti. Quindi, utilizza plugin core Maven (si riconosce un nucleo Maven plug-in per la sua groupId: org.apache.maven.plugins) per fare i compiti richiesti: plug-in compilatore per le classi di compilazione, plug-in di prova per l'esecuzione di test, e quindi per ... Così, anche se non lo fai dichiarare questi plugin, sono legati all'esecuzione del ciclo di vita di Maven.
Alla directory principale del progetto Maven, è possibile eseguire il comando: mvn help:effective-pomper utilizzare efficacemente l'ultimo pom. Potresti vedere, tra le altre informazioni, i plugin allegati di Maven (specificati o meno nel tuo pom.xml), con la versione utilizzata, la loro configurazione e gli obiettivi eseguiti per ogni fase del ciclo di vita.

Nell'output del mvn help:effective-pomcomando, è possibile visualizzare la dichiarazione di questi plug-in core <build><plugins>nell'elemento, ad esempio:

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

Puoi avere maggiori informazioni a riguardo nell'introduzione del salvagente Maven nella documentazione di Maven .

Tuttavia, puoi dichiarare questi plugin quando vuoi configurarli con altri valori come valori predefiniti (ad esempio, l'hai fatto quando hai dichiarato il plugin del compilatore maven nel tuo pom.xml per regolare la versione JDK da usare) o quando desidera aggiungere alcune esecuzioni di plug-in non utilizzate per impostazione predefinita nel ciclo di vita di Maven.


Grazie per un'ampia spiegazione, ora è molto più chiaro per me. Anche su <java.version> - L'ho visto in alcuni frammenti di codice, forse quella era una proprietà personalizzata e ho erroneamente supposto che sia il modo di dichiarare la versione java, da quel momento in poi si attaccherà alla <maven.compiler.x>proprietà.
Plebejusz,

Sei il benvenuto, con piacere :) Inizialmente, non era mia intenzione svilupparmi così tanto ma quando ho iniziato, non potevo fermarmi :) Per `<java.version>` è molto probabile. Ci vediamo e buona maven!
davidxxx,

1
" non è un problema se il JDK del tuo JAVA_HOME è compatibile con le versioni specificate nel pom " questo non è (necessariamente) vero, controlla questo thread Stack Overflow per riferimento
A_Di-Matteo

2
@Robin A. Meade grazie per il feedback. Uso lo stivale a molla ma non lo sapevo. Personalmente non l'ho trovato abbastanza standard per essere usato o indicato come qualcosa da usare. L'avvio a molla offre alcune cose molto interessanti ma in alcuni casi le sue caratteristiche sono molto discutibili. Sovrascrivere il nome di una proprietà standard maven per non riempire sia l'origine che il jdk di destinazione appare davvero una cattiva idea poiché viene eseguita una sola volta per un'applicazione. Perdi lo standard per risparmiare una semplice linea XML nella tua applicazione. Woah! Che idea ...
davidxxx,

1
@ MasterJoe2 Lo trovi nella documentazione ufficiale di javac della versione 10: docs.oracle.com/javase/10/tools/javac.htm#JSWOR627 . Ho avuto spaccatura che la risposta in due parti, come che diventa troppo grande, si può anche osservare che: stackoverflow.com/questions/51692748/...
davidxxx

3

Nessuna delle soluzioni di cui sopra ha funzionato immediatamente per me. Quindi ho fatto quanto segue: -

  1. aggiunto

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

    in pom.xml

  2. Andato a Project Properties > Java Build Path, quindi rimosso la libreria di sistema JRE che puntava JRE1.5.

  3. Force ha aggiornato il progetto.


Quale versione specifichi per Java 10 e versioni successive? Sono 10 o 1.10?
MasterJoe2

@ MasterJoe2 da Java 9 e versioni successive è necessario scrivere il numero di versione così com'è (<versione> 10 </versione>), e per le versioni seguenti, è necessario aggiungere 1. davanti alla versione (<versione> 1.5 </version>)
ikbel benab

0

Considera l'alternativa:

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

Dovrebbe essere la stessa cosa, maven.compiler.source/maven.compiler.targetma la soluzione di cui sopra funziona per me, altrimenti la seconda ottiene la specifica del genitore (ho una matrioska di .pom)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.