在 Maven 中指定 Java 版本 - 属性和编译器插件之间的差异
Specifying Java version in maven - differences between properties and compiler plugin
我对 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 package
输出
maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---
...以及其他一些我没有声明的插件。
那么这些插件是 Maven pom 的默认隐藏部分吗?在属性和 Maven 插件配置元素中设置 source/target 之间有什么区别吗?
其他一些问题是 - 应使用哪种方式(如果它们不相等,则何时使用)?哪个最适合多模块项目?如果 pom 中指定的 Java 版本与 JAVA_HOME
中指定的版本不同会发生什么情况?
如何指定JDK版本?
使用以下三种方式中的任何一种:(1) Spring 启动功能,或使用 Maven 编译器插件与 (2) source
& target
或 (3) release
.
Spring开机
<java.version>
未在 Maven 文档中引用。
这是一个 Spring 引导特性。
它允许将源和目标 java 版本设置为相同的版本,例如此版本,以便为两者指定 java 1.8 :
1.8
使用Spring Boot.
就放心使用吧
maven-compiler-plugin
与 source
& target
- 使用
maven-compiler-plugin
或 maven.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.source
和 maven.compiler.target
(如果已定义)。
The -source
argument for the Java compiler.
Default value is: 1.6
.
User property is: maven.compiler.source
.
The -target
argument for the Java compiler.
Default value is: 1.6
.
User property is: maven.compiler.target
.
关于 source
和 target
的默认值,请注意
since the 3.8.0
of the maven compiler, the default values have changed from 1.5
to 1.6
.
maven-compiler-plugin
用 release
代替 source
& target
maven-compiler-plugin 3.6
及以后的版本提供了新的方式:
org.apache.maven.plugins
maven编译器插件
3.8.0
9
你也可以只声明 :
<properties>
<maven.compiler.release>9</maven.compiler.release>
</properties>
但目前无法使用,因为您使用的 maven-compiler-plugin
默认版本不依赖于足够新的版本。
Maven release
参数传达 release
: 我们可以从 Java 传递的 new JVM standard option 9 :
Compiles against the public, supported and documented API for a
specific VM version.
这种方式提供了一种标准方式来为 source
、target
和 bootstrap
JVM 选项指定相同的版本。
请注意,指定 bootstrap
是交叉编译的好习惯,如果您不进行交叉编译也不会受到伤害。
指定JDK版本的最佳方式是什么?
第一种方式(<java.version>
)仅在使用Spring引导时才允许。
对于Java8及以下:
关于其他两种方式:使用 maven-compiler-plugin
评估 maven.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 配置中的 source
和 target
版本不应优于 JAVA_HOME
引用的 JDK 版本.
JDK 的旧版本无法与更新的版本一起编译,因为它不知道其规范。
要根据使用的 JDK 获取有关源、目标和发布支持版本的信息,请参阅 java compilation : source, target and release supported versions。
如何处理 JAVA_HOME 引用的 JDK 与 pom 中指定的 java 目标 and/or 源版本不兼容的情况?
例如,如果您的 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>
您可以在 examples with maven compiler plugin 中获得更多详细信息。
它不会被询问,但当您指定源而不是目标时,情况可能会更复杂。它可能会根据源版本在目标中使用不同的版本。规则很特别:您可以在 the Cross-Compilation Options part.
中阅读它们
为什么在执行 Maven package
目标时在输出中跟踪编译器插件,即使您没有在 pom.xml 中指定它?
要编译您的代码并更普遍地执行 Maven 目标所需的所有任务,Maven 需要工具。因此,它使用核心 Maven 插件(您可以通过其 groupId
识别核心 Maven 插件:org.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>
...
您可以在 the introduction of the Maven lifeycle in the Maven documentation 中获得更多信息。
然而,当你想用其他值配置它们作为默认值时,你可以声明这些插件(例如,当你在 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 的 matrioska)
None 上面的解决方案立即对我有用。所以我遵循了这些步骤:
- 加入
pom.xml:
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
转到 Project Properties
> Java Build Path
,然后删除 JRE
指向 JRE1.5
.
的系统库
强制更新项目。
以下步骤对我很有帮助!想来分享给大家。
这些是我在 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 可以 download/fetch 将插件添加到项目中。 (对于 IntelijIDEA:右键单击 pom.xml -> 转到 maven -> 重新加载项目)。
请确保在您的 IDE 中配置所需的版本。
对于 NetBeans IDE,更改项目属性 - (Jersey Service) - 类别 > 来源 >
选择 'Source/Binary Format' 作为 1.8。
如果您使用的是 IntelliJ idea maven 构建。
我对 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 package
输出
maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---
...以及其他一些我没有声明的插件。
那么这些插件是 Maven pom 的默认隐藏部分吗?在属性和 Maven 插件配置元素中设置 source/target 之间有什么区别吗?
其他一些问题是 - 应使用哪种方式(如果它们不相等,则何时使用)?哪个最适合多模块项目?如果 pom 中指定的 Java 版本与 JAVA_HOME
中指定的版本不同会发生什么情况?
如何指定JDK版本?
使用以下三种方式中的任何一种:(1) Spring 启动功能,或使用 Maven 编译器插件与 (2) source
& target
或 (3) release
.
Spring开机
1.8<java.version>
未在 Maven 文档中引用。
这是一个 Spring 引导特性。
它允许将源和目标 java 版本设置为相同的版本,例如此版本,以便为两者指定 java 1.8 :
使用Spring Boot.
就放心使用吧maven-compiler-plugin
与 source
& target
- 使用
maven-compiler-plugin
或maven.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.source
和 maven.compiler.target
(如果已定义)。
The
-source
argument for the Java compiler.
Default value is:1.6
.
User property is:maven.compiler.source
.
The
-target
argument for the Java compiler.
Default value is:1.6
.
User property is:maven.compiler.target
.
关于 source
和 target
的默认值,请注意
since the 3.8.0
of the maven compiler, the default values have changed from 1.5
to 1.6
.
maven-compiler-plugin
用 release
代替 source
& target
maven-compiler-plugin
org.apache.maven.plugins maven编译器插件 3.8.0 93.6
及以后的版本提供了新的方式:
你也可以只声明 :
<properties>
<maven.compiler.release>9</maven.compiler.release>
</properties>
但目前无法使用,因为您使用的 maven-compiler-plugin
默认版本不依赖于足够新的版本。
Maven release
参数传达 release
: 我们可以从 Java 传递的 new JVM standard option 9 :
Compiles against the public, supported and documented API for a specific VM version.
这种方式提供了一种标准方式来为 source
、target
和 bootstrap
JVM 选项指定相同的版本。
请注意,指定 bootstrap
是交叉编译的好习惯,如果您不进行交叉编译也不会受到伤害。
指定JDK版本的最佳方式是什么?
第一种方式(<java.version>
)仅在使用Spring引导时才允许。
对于Java8及以下:
关于其他两种方式:使用 maven-compiler-plugin
评估 maven.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 配置中的 source
和 target
版本不应优于 JAVA_HOME
引用的 JDK 版本.
JDK 的旧版本无法与更新的版本一起编译,因为它不知道其规范。
要根据使用的 JDK 获取有关源、目标和发布支持版本的信息,请参阅 java compilation : source, target and release supported versions。
如何处理 JAVA_HOME 引用的 JDK 与 pom 中指定的 java 目标 and/or 源版本不兼容的情况?
例如,如果您的 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>
您可以在 examples with maven compiler plugin 中获得更多详细信息。
它不会被询问,但当您指定源而不是目标时,情况可能会更复杂。它可能会根据源版本在目标中使用不同的版本。规则很特别:您可以在 the Cross-Compilation Options part.
中阅读它们为什么在执行 Maven package
目标时在输出中跟踪编译器插件,即使您没有在 pom.xml 中指定它?
要编译您的代码并更普遍地执行 Maven 目标所需的所有任务,Maven 需要工具。因此,它使用核心 Maven 插件(您可以通过其 groupId
识别核心 Maven 插件:org.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>
...
您可以在 the introduction of the Maven lifeycle in the Maven documentation 中获得更多信息。
然而,当你想用其他值配置它们作为默认值时,你可以声明这些插件(例如,当你在 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 的 matrioska)
None 上面的解决方案立即对我有用。所以我遵循了这些步骤:
- 加入
pom.xml:
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
</properties>
转到
的系统库Project Properties
>Java Build Path
,然后删除 JRE 指向JRE1.5
.强制更新项目。
以下步骤对我很有帮助!想来分享给大家。
这些是我在 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 可以 download/fetch 将插件添加到项目中。 (对于 IntelijIDEA:右键单击 pom.xml -> 转到 maven -> 重新加载项目)。
请确保在您的 IDE 中配置所需的版本。
对于 NetBeans IDE,更改项目属性 - (Jersey Service) - 类别 > 来源 > 选择 'Source/Binary Format' 作为 1.8。
如果您使用的是 IntelliJ idea maven 构建。