我使用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能够使用它.第一个问题是:

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

我找不到明确的答案,但在研究过程中,我发现您也可以通过以下方式指定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 ---

...还有一些我没有声明的插件.

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?

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

推荐答案

How to specify the JDK version?

使用三种方法中的任何一种:(1)Spring bootstrap 功能,或者使用Maven编译器插件,使用(2)source&;target或(3)与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

如果使用弹簧靴,请随意使用.

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

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.

关于sourcetarget的默认值,请注意

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

  1. maven编译器插件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:new JVM standard option ,我们可以从Java 9传递:

针对公共的、受支持的和有文档记录的 特定的VM版本.

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?

只有在使用弹簧靴的情况下,才允许使用第一种方式(<java.version>).

For Java 8 and below :

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

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

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

From Java 9 :

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

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

如果JAVA_HOME引用的JDK与pom中指定的版本兼容,这不是问题,但是为了确保更好的交叉编译兼容性,可以考虑添加bootstrap JVM选项,并将target版本的rt.jar的路径作为值.

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.

要根据使用的JDK获取源、目标和版本支持的信息,请参阅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.8\bin\javac</executable>                
    </configuration>
</plugin>

你可能会在examples with maven compiler plugin中了解更多细节.


它并没有被问到,但更复杂的情况是当您指定源而不是目标时.它可能会根据源版本在目标中使用不同的版本.规则很特别:你可以在the Cross-Compilation Options part本书中读到.


Why the compiler plugin is traced in the output at the execution of the Maven 100 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.

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生命周期中默认不使用的插件执行时,您可以声明这些插件.

Java相关问答推荐

当耗时的代码完成时,Circular ProgressIndicator显示得太晚

ActivityCompat.请求收件箱自动拒绝权限

将linkedHashMap扩展到Java中的POJO类

我无法将附件发送到NetBeans之外

基本时态运算的ISO-8601周数据表示法

现场观看Android Studio中的变化

当返回Mono<;Something>;时,不会调用Mono<;void>;.flatMap

如何使用值中包含与号的查询参数创建一个java.net.URI

按属性值从流中筛选出重复项

对于亚洲/香港,使用ResolverStyle.STRICT的LocalDate.parse返回意外结果

如何只修改父类ChroniclerView位置0处的第一个嵌套ChroniclerView(child)元素?

为什么同步数据块无效?

如何在透视表中添加对计数列的筛选?

如何以编程方式保存workBench.xmi?

JFree Chart从图表中删除边框

如何处理两个几乎相同的XSD文件?

如何使用Rascal Evaluator从编译的JAR访问Rascal函数?

使用Java线程进行并行编程

错误:JOIN/ON的参数必须是boolean类型,而不是bigint类型.Java Spring启动应用程序

UuidGenerator Bean 类型不匹配?