在 Maven 中指定 Java 版本 - 属性和编译器插件之间的差异 [英] Specifying Java version in maven - differences between properties and compiler plugin

查看:43
本文介绍了在 Maven 中指定 Java 版本 - 属性和编译器插件之间的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Maven 不是很有经验,在尝试多模块项目时,我开始想知道如何为父 Maven pom 中的所有子模块指定 Java 版本.直到今天我只使用:

<java.version>1.8</java.version></属性>

...但是在研究时我发现您也可以在 Maven 编译器插件中指定 Java 版本,如下所示:

<插件><artifactId>maven-compiler-plugin</artifactId><配置><来源>1.8</来源><目标>1.8</目标></配置></插件></插件>

然后将其包装到插件管理标签中以启用子 poms 使用它.所以第一个问题是:

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

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

<maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></属性>

...这表明编译器插件在那里,即使我没有明确声明它.使用

运行 mvn package 输出

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

...以及其他一些我没有声明的插件.

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

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

解决方案

如何指定JDK版本?

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

Spring Boot

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

    1.8

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

maven-compiler-plugin with source &目标

  1. 使用 maven-compiler-pluginmaven.compiler.source/maven.compiler.target 属性是等效的.

确实是这样:

<插件><artifactId>maven-compiler-plugin</artifactId><配置><来源>1.8</来源><目标>1.8</目标></配置></插件></插件>

相当于:

<maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></属性>

根据编译器插件的Maven文档因为编译器配置中的 元素使用属性 maven.compiler.sourcemaven.compiler.target 如果它们被定义了.

<块引用>

来源

<块引用>

Java 编译器的 -source 参数.
默认值为:1.6.
用户属性为:maven.compiler.source.

<块引用>

目标

<块引用>

Java 编译器的 -target 参数.
默认值为:1.6.
用户属性为:maven.compiler.target.

关于sourcetarget的默认值,注意3.8.0maven 编译器,默认值已从 1.5 更改为 1.6.

maven-compiler-plugin 使用 release 而不是 source &目标

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

    org.apache.maven.pluginsMaven 编译器插件3.8.09

你也可以只声明:

<maven.compiler.release>9</maven.compiler.release></属性>

但此时它不会工作,因为您使用的 maven-compiler-plugin 默认版本不依赖于足够新的版本.

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

<块引用>

针对公共、支持和记录的 API 进行编译,用于特定的虚拟机版本.

这种方式提供了一种标准方式来为 sourcetargetbootstrap JVM 选项指定相同的版本.
请注意,指定 bootstrap 是交叉编译的好习惯,如果您不进行交叉编译也不会有什么坏处.


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

第一种方式 () 仅当您使用 Spring Boot 时才允许.

对于 Java 8 及以下版本:

关于另外两种方式:使用 评估 maven.compiler.source/maven.compiler.target 属性 maven-compiler-plugin,您可以使用其中一种.事实并没有改变,因为最终这两个解决方案依赖于相同的属性和相同的机制:maven 核心编译器插件.

好吧,如果您不需要在编译器插件中指定除 Java 版本之外的其他属性或行为,那么使用这种方式更有意义,因为它更简洁:

<maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></属性>

来自 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 不知道如何编译.
从它的角度来看,它是一个未知的JDK版本,因为它是在它之后发布的.
在这种情况下,您应该通过这种方式配置Maven编译器插件来指定JDK:

<groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><配置><来源>1.8</来源><目标>1.8</目标><compilerVersion>1.8</compilerVersion><fork>true</fork><executable>D:jdk1.8injavac</executable></配置></插件>

您可以在 中了解更多详细信息Maven 编译器插件示例.


它没有被问到,但可能更复杂的情况是当您指定源而不是目标时.它可能会根据源版本在目标中使用不同的版本.规则是特殊的:您可以在 the Cross-编译选项部分.


为什么编译器插件在执行 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 命令的输出中,您可以在 元素中看到这些核心插件的声明,例如:

<代码>...<插件><artifactId>maven-clean-plugin</artifactId><version>2.5</version><执行><执行><id>default-clean</id><phase>clean</phase><目标><目标>干净</目标></目标></执行></执行></插件><插件><artifactId>maven-resources-plugin</artifactId><version>2.6</version><执行><执行><id>default-testResources</id><阶段>过程测试资源</阶段><目标><goal>testResources</goal></目标></执行><执行><id>默认资源</id><阶段>流程资源</阶段><目标><目标>资源</目标></目标></执行></执行></插件><插件><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><执行><执行><id>默认编译</id><阶段>编译</阶段><目标><目标>编译</目标></目标></执行><执行><id>default-testCompile</id><phase>test-compile</phase><目标><goal>testCompile</goal></目标></执行></执行></插件>...

您可以在介绍Maven 文档中的 Maven 生命周期.

尽管如此,当您想将它们配置为其他值作为默认值时,您可以声明这些插件(例如,您在 pom.xml 中声明 maven-compiler 插件以调整要使用的 JDK 版本时这样做)或者当你想添加一些在 Maven 生命周期中默认不使用的插件执行时.

I'm not very experienced with Maven and while experimenting with multi-module project I started wondering how can I specify Java version for all my child modules in parent Maven pom. Until today I was using just:

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

...but when researching I found that you can also specify Java version in Maven compiler plugin, like that:

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

And then wrap this into plugin management tag to enable child poms usage of this. So the first question is this:

What are the differences beetwen setting Java version in properties and in Maven compiler plugin?

I couldn't find clear answer but in process of researching I found that you can also specify Java version in this way:

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

...which suggest that compiler plugin is there even if I don't explicit declare it. Running mvn package outputs with

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

...and some other plugins that I didn't declare.

So are those plugins default, hidden part of Maven pom? Are there any differences between setting source/target in properties and in Maven plugin configuration element?

Some other questions are - which way should be used (and when if they are not equal)? Which one is best for multi-module project and what happens if Java version specified in pom is different than version pointed in JAVA_HOME?

解决方案

How to specify the JDK version?

Use any of three ways: (1) Spring Boot feature, or use Maven compiler plugin with either (2) source & target or (3) with release.

Spring Boot

  1. <java.version> is not referenced in the Maven documentation.
    It is a Spring Boot specificity.
    It allows to set the source and the target java version with the same version such as this one to specify java 1.8 for both :

    1.8

Feel free to use it if you use Spring Boot.

maven-compiler-plugin with source & target

  1. Using maven-compiler-plugin or maven.compiler.source/maven.compiler.target properties are equivalent.

That is indeed :

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

is equivalent to :

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

according to the Maven documentation of the compiler plugin since the <source> and the <target> elements in the compiler configuration use the properties maven.compiler.source and maven.compiler.target if they are defined.

source

The -source argument for the Java compiler.
Default value is: 1.6.
User property is: maven.compiler.source.

target

The -target argument for the Java compiler.
Default value is: 1.6.
User property is: maven.compiler.target.

About the default values for source and target, note that since the 3.8.0 of the maven compiler, the default values have changed from 1.5 to 1.6.

maven-compiler-plugin with release instead of source & target

  1. The maven-compiler-plugin 3.6 and later versions provide a new way :

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

You could also declare just :

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

But at this time it will not work as the maven-compiler-plugin default version you use doesn't rely on a recent enough version.

The Maven release argument conveys release : a new JVM standard option that we could pass from Java 9 :

Compiles against the public, supported and documented API for a specific VM version.

This way provides a standard way to specify the same version for the source, the target and the bootstrap JVM options.
Note that specifying the bootstrap is a good practice for cross compilations and it will not hurt if you don't make cross compilations either.


Which is the best way to specify the JDK version?

The first way (<java.version>) is allowed only if you use Spring Boot.

For Java 8 and below :

About the two other ways : valuing the maven.compiler.source/maven.compiler.target properties or using the maven-compiler-plugin, you can use one or the other. It changes nothing in the facts since finally the two solutions rely on the same properties and the same mechanism : the maven core compiler plugin.

Well, if you don't need to specify other properties or behavior than Java versions in the compiler plugin, using this way makes more sense as this is more concise:

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

From Java 9 :

The release argument (third point) is a way to strongly consider if you want to use the same version for the source and the target.

What happens if the version differs between the JDK in JAVA_HOME and which one specified in the pom.xml?

It is not a problem if the JDK referenced by the JAVA_HOME is compatible with the version specified in the pom but to ensure a better cross-compilation compatibility think about adding the bootstrap JVM option with as value the path of the rt.jar of the target version.

An important thing to consider is that the source and the target version in the Maven configuration should not be superior to the JDK version referenced by the JAVA_HOME.
A older version of the JDK cannot compile with a more recent version since it doesn't know its specification.

To get information about the source, target and release supported versions according to the used JDK, please refer to java compilation : source, target and release supported versions.


How handle the case of JDK referenced by the JAVA_HOME is not compatible with the java target and/or source versions specified in the pom?

For example, if your JAVA_HOME refers to a JDK 1.7 and you specify a JDK 1.8 as source and target in the compiler configuration of your pom.xml, it will be a problem because as explained, the JDK 1.7 doesn't know how to compile with.
From its point of view, it is an unknown JDK version since it was released after it.
In this case, you should configure the Maven compiler plugin to specify the JDK in this way :

<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.8injavac</executable>                
    </configuration>
</plugin>

You could have more details in examples with maven compiler plugin.


It is not asked but cases where that may be more complicated is when you specify source but not target. It may use a different version in target according to the source version. Rules are particular : you can read about them in the Cross-Compilation Options part.


Why the compiler plugin is traced in the output at the execution of the Maven package goal even if you don't specify it in the pom.xml?

To compile your code and more generally to perform all tasks required for a maven goal, Maven needs tools. So, it uses core Maven plugins (you recognize a core Maven plugin by its groupId : org.apache.maven.plugins) to do the required tasks : compiler plugin for compiling classes, test plugin for executing tests, and so for... So, even if you don't declare these plugins, they are bound to the execution of the Maven lifecycle.
At the root dir of your Maven project, you can run the command : mvn help:effective-pom to get the final pom effectively used. You could see among other information, attached plugins by Maven (specified or not in your pom.xml), with the used version, their configuration and the executed goals for each phase of the lifecycle.

In the output of the mvn help:effective-pom command, you could see the declaration of these core plugins in the <build><plugins> element, for example :

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

You can have more information about it in the introduction of the Maven lifeycle in the Maven documentation.

Nevertheless, you can declare these plugins when you want to configure them with other values as default values (for example, you did it when you declared the maven-compiler plugin in your pom.xml to adjust the JDK version to use) or when you want to add some plugin executions not used by default in the Maven lifecycle.

这篇关于在 Maven 中指定 Java 版本 - 属性和编译器插件之间的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆