Maven中的Java版本-属性和编译器插件之间的差异

pnwntuvh  于 11个月前  发布在  Maven
关注(0)|答案(7)|浏览(173)

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


然后将其 Package 到插件管理标签中,以使子poms能够使用它。所以第一个问题是:

在属性中设置Java版本和在Maven编译器插件中设置Java版本有什么区别?

我找不到明确的答案,但在研究过程中,我发现你也可以用这种方式指定Java版本:

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


.这表明编译器插件存在,即使我没有显式声明它。

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


.和其他一些插件,我没有声明.

那么这些插件是默认的,Maven pom的隐藏部分吗?在属性中设置源/目标和在Maven插件配置元素中设置源/目标有什么区别吗?

其他一些问题是-应该使用哪种方式(以及何时使用,如果它们不相等)?哪种方式最适合多模块项目?如果pom中指定的Java版本与JAVA_HOME中指定的版本不同,会发生什么?

iq0todco

iq0todco1#

如何指定JDK版本?

使用以下三种方式中的任何一种:(1)Sping Boot 功能,或使用Maven编译器插件(2)sourcetarget或(3)release

Sping Boot

  1. Maven文档中没有引用<java.version>
    这是Sping Boot 的特性。
    它允许将源和目标Java版本设置为相同的版本,例如将两者指定为Java 1.8:
    1.8
    如果您使用Sping Boot ,请随意使用它。

maven-compiler-pluginsourcetarget

1.使用maven-compiler-pluginmaven.compiler.source/maven.compiler.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 documentation of the compiler plugin,因为编译器配置中的<source><target>元素使用属性maven.compiler.sourcemaven.compiler.target(如果定义了它们)。

来源

Java编译器的-source参数。

:自3.8.0起默认值从1.5更改为1.6。自3.9.0起默认值从1.6更改为1.7

默认值为:1.7。
用户属性为:maven.compiler.source

目标

Java编译器的-target参数。

:自3.8.0起默认值从1.5更改为1.6。自3.9.0起默认值从1.6更改为1.7

默认值为:1.6
用户属性为:maven.compiler.target
关于sourcetarget的默认值,请注意since the 3.8.0 of the maven compiler, the default values have changed from 1.5 to 1.6

maven-compiler-pluginrelease,而不是sourcetarget

  1. maven-compiler-plugin 3.6和更高版本提供了一种新的方法:
    org.apache.maven.plugins maven-compiler-plugin 3.8.0 9
    你也可以声明:
<properties>
    <maven.compiler.release>9</maven.compiler.release>
</properties>


但此时它将无法工作,因为您使用的maven-compiler-plugin默认版本不依赖于足够新的版本。
Maven release参数传递了release:一个新的JVM标准选项,我们可以从Java 9传递:
针对特定VM版本的公共、受支持和文档化API进行编译。
这种方式为sourcetargetbootstrap JVM选项指定相同的版本提供了一种标准方法。
请注意,指定bootstrap是交叉编译的一个很好的实践,如果您不进行交叉编译,也不会有什么坏处。

指定JDK版本的最佳方式是什么?

第一种方式(<java.version>)仅在使用Sping Boot 时才允许。

Java 8及以下版本:

关于另外两种方式:使用maven-compiler-pluginmaven.compiler.source/maven.compiler.target属性进行赋值,您可以使用一个或另一个。它不会改变事实,因为最终这两个解决方案依赖于相同的属性和相同的机制:maven核心编译器插件。
如果您不需要在编译器插件中指定Java版本以外的其他属性或行为,则使用这种方式更有意义,因为它更简洁:

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

来自Java 9:

release参数(第三点)是一种强烈考虑是否要对源和目标使用相同版本的方法。

如果JAVA_HOME中的JDK版本与pom.xml中指定的版本不同,会发生什么?

如果JAVA_HOME引用的JDK与pom中指定的版本兼容,这不是问题,但为了确保更好的交叉编译兼容性,请考虑添加bootstrap JVM选项,其值为target版本的rt.jar的路径。
需要考虑的一件重要事情是,Maven配置中的sourcetarget版本不应该比JAVA_HOME引用的JDK版本更上级。
旧版本的JDK不能与新版本编译,因为它不知道它的规范。
要根据所使用的JDK获取有关源,目标和发布支持版本的信息,请参阅java编译:源,目标和发布支持版本。

JAVA_HOME引用的JDK与pom中指定的java目标和/或源版本不兼容的情况如何处理?

例如,如果您的JAVA_HOME引用JDK 1.7,并且您在pom.xml的编译器配置中指定JDK 1.8作为源和目标,这将是一个问题,因为正如所解释的那样,JDK 1.7不知道如何编译。
从它的Angular 来看,它是一个未知的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>


您可以在examples with maven compiler plugin中了解更多详细信息。
这不是要求,但情况可能更复杂的是当你指定源,但不是目标。它可能会使用不同的版本在目标根据源版本。规则是特别的:你可以在the Cross-Compilation Options part中阅读它们。

为什么编译器插件在执行Maven package目标时会在输出中被跟踪,即使您没有在pom.xml中指定它?

为了编译代码,更一般地说,为了执行maven目标所需的所有任务,Maven需要工具。(您可以通过groupIdorg.apache.maven.plugins识别核心Maven插件)来执行所需的任务:用于编译类的编译器插件,用于执行测试的测试插件,等等.所以,即使你不声明这些插件,它们被绑定到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>
  ...


您可以在the introduction of the Maven lifeycle in the Maven documentation中了解更多信息。
然而,当您想要将其他值配置为默认值时,您可以声明这些插件(例如,当您在pom.xml中声明maven编译器插件以调整要使用的JDK版本时,您这样做了),或者当您想要添加一些在Maven生命周期中默认不使用的插件执行时。

daolsyd0

daolsyd02#

上面的解决方案没有一个对我直接起作用。所以我遵循了以下步骤:
1.添加pom.xml:

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

字符串
1.转到Project Properties > Java Build Path,然后删除指向JRE1.5的JRE系统库。

  1. Force更新了项目。
eoigrqb6

eoigrqb63#

下面的步骤对我来说就像魅力一样!所以想和大家分享。
这些是我在pom.xml文件中添加的行,用于基本项目。我使用Java 12(您可以替换您的11,10,1.8等)。

<properties>
    <maven.compiler.source>12</maven.compiler.source>
    <maven.compiler.target>12</maven.compiler.target>
</properties>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <release>12</release>
            </configuration>
        </plugin>
    </plugins>
</build>

字符串
更改pom文件后,请重新加载您的项目,以便IDE可以将插件下载/获取到项目中。(对于IntelijIDEA:右键单击pom.xml ->转到maven ->插件项目)。
请确保在你的IDE中也配置了你想要的版本。

0tdrvxhp

0tdrvxhp4#

如果你使用的是IntelliJ idea maven build。


的数据

tyg4sfes

tyg4sfes5#

考虑另一种选择:

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

字符串
它应该是相同的事情maven.compiler.source/maven.compiler.target,但上述解决方案为我工作,否则第二个得到父规范(我有一个matrioska的.pom)

u3r8eeie

u3r8eeie6#

Davids的解决方案是正确的,我想添加所需的设置Maven插件编译主源代码和测试源代码与不同的Java发布/语言版本。
属性maven.compiler.release由Maven编译器插件用于主源代码和测试源代码。因此,无法通过简单地设置属性(使用Maven编译器插件的3.11.0版本进行测试)来编译与主源代码不同的JDK版本的测试源代码。
因此,您必须覆盖default-compiledefault-testCompile的执行,如下所示:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.11.0</version>
    <executions>
        <execution>
            <id>default-compile</id>
            <configuration>
                <release>8</release>
            </configuration>
        </execution>
        <execution>
            <id>default-testCompile</id>
            <configuration>
                 <release>17</release>
            </configuration>
        </execution>
    </executions>
</plugin>

字符串
使用这个设置,我能够用不同的JDK版本编译一个多模块项目的单个版本,然后剩下的。
为什么对我来说设置maven.compiler.sourcemaven.compiler.test不同还不够?
通过只设置这些属性,编译器插件能够毫无问题地编译Java 11代码。这实际上不是我想要的。

zbq4xfa0

zbq4xfa07#

对于NetBeans IDE,将项目属性-(Jersey Service)- Categories > Sources > Selected 'Source/Binary Format'更改为1.8。

相关问题