MavenでのJavaバージョンの指定-プロパティとコンパイラプラグインの違い


178

私はmavenに精通していないので、マルチモジュールプロジェクトを実験しているときに、親maven pomのすべての子モジュールにjavaバージョンを指定するにはどうすればよいか疑問に思い始めました。今日まで、私はちょうど使用していました:

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

しかし、調査したところ、次のようにmavenコンパイラプラグインでJavaバージョンを指定できることもわかりました。

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

そして、これをプラグイン管理タグにラップして、子pomsがこれを使用できるようにします。最初の質問は、プロパティとmavenコンパイラプラグインのJavaバージョンの設定の違い何ですか?

明確な答えは見つかりませんでしたが、調査の過程で、次のように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プラグイン構成要素のソース/ターゲットの設定に違いはありますか?

他のいくつかの質問は-どの方法を使用する必要がありますか(それらが等しくない場合)?マルチモジュールプロジェクトに最適なのはどれですか。pomで指定されたJavaバージョンがJAVA_HOMEで指定されたバージョンと異なる場合はどうなりますか?

回答:


288

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それらが定義されている場合は同等です。

ソース

-sourceJavaコンパイラの引数。
デフォルト値はです1.6
ユーザープロパティはですmaven.compiler.source

目標

-targetJavaコンパイラの引数。
デフォルト値はです1.6
ユーザープロパティはですmaven.compiler.target

デフォルトの値についてsourcetargetすることを、ノート ので、3.8.0Mavenのコンパイラの、デフォルト値から変更されている1.51.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ます。Java9 から渡すことができる新しいJVM標準オプション

特定のVMバージョンについて、公開され、サポートされ、文書化されているAPIに対してコンパイルします。

この方法では、のために同じバージョンを指定するための標準的な方法を提供sourcetargetおよびbootstrapJVMオプションを。
を指定することbootstrapはクロスコンパイルに適した方法であり、クロスコンパイルを行わなくても問題はありません。


JDKバージョンを指定する最良の方法はどれですか?

最初の方法(<java.version>)は、Spring Bootを使用する場合にのみ許可されます。

Java 8以下の場合:

その他の2つの方法について:maven.compiler.source/ maven.compiler.targetプロパティを評価するか、を使用してmaven-compiler-plugin、どちらか一方を使用できます。最後に2つのソリューションが同じプロパティと同じメカニズムに依存しているため、これは事実を変更しません:Mavenコアコンパイラプラグイン。

まあ、コンパイラプラグインでJavaバージョン以外のプロパティや動作を指定する必要がない場合は、この方法を使用する方が簡潔です。

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

Java 9から:

release引数(第3ポイント)を使用すると、ソースとターゲットのための同じバージョンを使用したい場合は、強く考慮するための方法です。

JAVA_HOMEのJDKとpom.xmlで指定されたJDKのバージョンが異なる場合はどうなりますか?

によって参照されるJDK JAVA_HOMEがpomで指定されたバージョンと互換性がある場合は問題ありませんが、クロスコンパイルの互換性を高めるbootstraprt.jarは、targetバージョンのパスを値としてJVMオプションを追加することを検討してください。

考慮すべき重要なことは、ということであるsourcetargetMavenの構成のバージョンがで参照されるJDKのバージョンよりも優れてはなりませんJAVA_HOME
JDKの古いバージョンは、その仕様を知らないため、新しいバージョンでコンパイルできません。

使用されているJDKに応じて、ソース、ターゲット、リリースのサポートされているバージョンに関する情報を取得するには、javaコンパイル:ソース、ターゲット、リリースのサポートされているバージョンを参照してください。


JAVA_HOMEによって参照されるJDKのケースをどのように処理するかは、pomで指定されたJavaターゲットやソースバージョンと互換性がありませんか?

たとえばJAVA_HOME、JDK 1.7を参照していて、pom.xmlのコンパイラー構成でソースおよびターゲットとしてJDK 1.8を指定した場合、JDK 1.7でコンパイルする方法がわからないため、問題になります。 。
その観点から、それはその後リリースされたので、未知のJDKバージョンです。
この場合、次の方法でJDKを指定するようにMavenコンパイラプラグインを設定する必要があります。

<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コンパイラプラグインを使用した例では、詳細を確認できます


質問はされませんが、ソースを指定してターゲットを指定しない場合は、さらに複雑になる可能性があります。ソースバージョンに応じて、ターゲットで異なるバージョンを使用する場合があります。ルールは特別です。それらについては、クロスコンパイルオプションの部分で読むことができます。


コンパイラプラグインがpackagepom.xmlで指定されていなくても、Maven ゴールの実行時に出力でトレースされるのはなぜですか?

コードをコンパイルし、より一般的にはMavenの目標に必要なすべてのタスクを実行するには、Mavenにツールが必要です。だから、それは(あなたがすることによって、そのコアMavenプラグインを認識コアのMavenプラグインを使用していますgroupIdorg.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ライフサイクルの紹介をご覧ください。

それでも、これらのプラグインをデフォルト値として他の値で構成したい場合(たとえば、pom.xmlでmaven-compilerプラグインを宣言して、使用するJDKバージョンを調整したときに)、またはMavenライフサイクルでデフォルトで使用されないプラグイン実行を追加したい。


たくさんの説明をありがとう、今では私にはずっとはっきりしています。<java.version>についても-これはいくつかのコードスニペットで見たことがあります。おそらくカスタムプロパティであり、それがjavaバージョンを宣言する方法であると誤って想定し、今後はこの<maven.compiler.x>プロパティに固執することになります。
Plebejusz

喜んで大歓迎です:)最初は、あまり開発するつもりはありませんでしたが、始めたときに止めることができませんでした:) `<java.version>`の場合は、非常に可能性が高いです。またね、いいメイヴェン!
davidxxx

1
JAVA_HOMEのJDKがpom内の指定されたバージョンと互換性がある場合は問題ありません。これは(必ずしも)trueではありません。参照のためにこのスタックオーバーフロースレッドを確認してください
A_Di-Matteo

2
@Robin A. Meadeからのフィードバックに感謝します。私は春のブーツを使用していますが、それを知りませんでした。個人的には、使用するために使用または参照するのに十分なほど標準的であるとは思いません。春のブーツはいくつかの非常に興味深いものを提供しますが、場合によってはその機能は非常に議論の余地があります。ソースとターゲットの両方のjdkを埋めないように標準のmavenプロパティの名前をオーバーライドすることは、アプリケーションに対して1回実行されるだけなので、実際には悪い考えです。アプリケーションの単純なxml行を節約するための標準を失います。うわー!なんというアイデア...
davidxxx 2017年

1
@ MasterJoe2これは、10バージョンの公式javacドキュメントであるdocs.oracle.com/javase/10/tools/javac.htm#JSWOR627にあります。私は2つの部分で答えが大きすぎるなっているようなことを分割していた、あなたはまた、その時に見ることができます: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

Java 9以降のバージョンの@ MasterJoe2では、バージョン番号をそのまま書き込む必要があります(<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なければなりませんが、上記の解決策は私にとってはうまくいきます、そうでなければ2番目のものは親仕様を取得します(私は.pomのmatrioskaを持っています)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.