在maven中指定Java版本-属性和编译器插件之间的区别

我对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使用这个。第一个问题是:

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

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

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

...这表明编译器插件是存在的,即使我没有显式声明它。运行mvn package输出

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

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

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

其他一些问题是——应该用哪种方式(如果它们不相等,什么时候用)?哪一个是最好的多模块项目,如果Java版本指定的pom是不同的版本指向JAVA_HOME?

238803 次浏览

如何指定JDK版本?

使用三种方式中的任何一种:(1)Spring Boot特性,或使用Maven编译器插件(2)source &target或(3)与release

春天的引导

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

    1.8

如果您使用Spring Boot,请随意使用它。

maven-compiler-pluginsource &target

  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文档 因为编译器配置中的<source><target>元素在定义时使用属性maven.compiler.sourcemaven.compiler.target

source

Java编译器的-source参数。
请注意:自3.8.0以来,默认值已从1.5更改为1.6。自3.9.0以来,默认值已经从1.6更改为1.7
缺省值:1.7。
用户属性为:maven.compiler.source

target

Java编译器的-target参数。
请注意:自3.8.0以来,默认值已从1.5更改为1.6。自3.9.0以来,默认值已经从1.6更改为1.7
默认值:1.6
用户属性为:maven.compiler.target

关于sourcetarget的默认值,请注意 自maven编译器的__ABC0开始,默认值已从__ABC1更改为1.6 . < / p >

release代替source &target

  1. maven-compiler-plugin 3.6及后续版本提供了一种新方法:

    org.apache.maven.plugins maven-compiler-plugin 3.8.0 9

你也可以声明just:

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

但此时它将不起作用,因为你使用的maven-compiler-plugin默认版本不依赖于足够最新的版本。

Maven release参数传递了release:一个我们可以从Java 9传递的新的JVM标准选项:

针对一个公共的、受支持的和文档化的API编译

.指定虚拟机版本
这种方式提供了一种标准的方法来为sourcetargetbootstrap JVM选项指定相同的版本。
注意,指定bootstrap是交叉编译的一个很好的实践,如果你不进行交叉编译,它也不会造成伤害

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

第一种方法(<java.version>)仅在使用Spring 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中指定的JDK版本不同,会发生什么情况?

如果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不知道如何编译。
从它的角度来看,它是一个未知的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编译器插件的例子中获得更多细节。


这不是被问到的问题,但当你指定源而不指定目标时,情况可能会更复杂。它可以根据源版本在目标中使用不同的版本。规则是特殊的:你可以在交叉编译选项部分中读到它们。


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

要编译代码,更一般地执行maven目标所需的所有任务,maven需要工具。因此,它使用核心Maven插件(你可以通过它的groupId: org.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>
...

你可以在Maven文档中Maven生命周期的介绍中获得更多关于它的信息。

然而,当您想要将这些插件配置为默认值时(例如,当您在pom.xml中声明Maven -compiler插件以调整使用的JDK版本时),或者当您想要添加一些在Maven生命周期中默认不使用的插件执行时,您可以声明这些插件。

考虑另一种选择:

<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的矩阵)

以上的解决方案都不适合我。所以我采取了以下步骤:

  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,然后删除JRE 指向JRE1.5的系统库

  2. 强制更新项目。

下面的步骤对我来说很有魅力!所以想和大家分享一下。

这些是我在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中配置所需的版本。

对于NetBeans IDE,更改项目属性- (Jersey Service) -类别>来源的在 选择“源/二进制格式”为1.8.

如果您正在使用IntelliJ idea maven构建。

enter image description here