在maven中指定java版本 - 属性和编译器插件之间的差异

时间:2016-08-10 19:35:44

标签: java maven maven-3 maven-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包输出
maven-compiler-plugin:3.1:compile (default-compile) @ testproj ---

和其他一些我没有声明的插件。 那些插件是默认的,隐藏的部分是maven pom吗?在属性和maven插件配置元素中设置源/目标是否有任何差异?

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

6 个答案:

答案 0 :(得分:219)

如何指定JDK版本?

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

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

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

2)使用maven-compiler-pluginmaven.compiler.source / maven.compiler.target属性指定sourcetarget是等效的。

<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>
根据{{​​3}},

是等效的 由于编译器配置中的<source><target>元素使用属性maven.compiler.sourcemaven.compiler.target(如果已定义)。

  

Maven documentation of the compiler plugin

     

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

     

source

     

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

关于sourcetarget的默认值,请注意  target

3)maven-compiler-plugin 3.6及更高版本提供了一种新方式:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.0</version>
    <configuration>
        <release>9</release>
    </configuration>
</plugin>

您也可以声明:

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

但此时它不起作用,因为您使用的maven-compiler-plugin默认版本并不依赖于最近的版本。

Maven release参数传达release:我们可以从Java 9传递的since the 3.8.0 of the maven compiler, the default values have changed from 1.5 to 1.6

  

针对a的公共,支持和记录的API进行编译   特定的VM版本。

这种方式提供了一种标准方法,可以为sourcetargetbootstrap JVM选项指定相同的版本。
请注意,指定bootstrap是交叉编译的好习惯,如果您不进行交叉编译也不会受到影响。

指定JDK版本的最佳方式是哪种?

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

对于Java 8及更低版本:

关于其他两种方式:使用maven.compiler.source评估maven.compiler.target / maven-compiler-plugin属性,您可以使用其中一种。它在事实上没有任何改变,因为最终这两个解决方案依赖于相同的属性和相同的机制: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选项,这不是问题。重视rt.jar版本的target的路径。

需要考虑的一件重要事情是,Maven配置中的sourcetarget版本不应优于JAVA_HOME引用的JDK版本。
旧版本的JDK无法使用更新版本进行编译,因为它不了解其规范。

要根据使用的JDK获取有关源,目标和发行版支持版本的信息,请参阅new JVM standard option

如何处理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>

您可以在java compilation : source, target and release supported versions中获得更多详细信息。

没有被问到,但是当你指定来源而不是目标时,可能更复杂的情况。根据源版本,它可能在目标中使用不同的版本。规则很特别:您可以在examples with maven compiler plugin中了解它们。

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

要编译代码,更一般地说,为了执行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 Cross-Compilation Options part中获得有关它的更多信息。

然而,当你想用其他值配置它们作为默认值时,可以声明这些插件(例如,你在pom.xml中声明maven-compiler插件以调整要使用的JDK版本时就这样做了)或者当您想要添加默认情况下在Maven生命周期中未使用的某些插件执行时。

答案 1 :(得分:1)

以上解决方案均无法立即为我工作。所以我做了以下事情:-

  1. 已添加

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

    在pom.xml中

  2. 转到项目Properties> Java Build Path,然后删除JRE     指向JRE1.5的系统库。

  3. 强制更新了项目。

答案 2 :(得分:1)

以下步骤对我来说就像魅力一样!所以想与大家分享。

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

答案 3 :(得分:0)

考虑替代方案:

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

答案 4 :(得分:0)

对于 NetBeans IDE,更改项目属性 - (Jersey Service) - Categories > Sources > 选择“源/二进制格式”为 1.8。

答案 5 :(得分:-2)

解决此问题的其他方法是重写java变量:

在命令中

Windows

set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_271
  • 可以是其他Java版本的位置

Linux或Mac

export JAVA_HOME=<java-8-home-folder>

要验证版本,请在命令中输入:

mvn –version

如果一切都很好,则外观如下:

Apache Maven 3.6.2 (40f52333136460xxxxxxxxxxxxxxxxxxxx; 2019-08-27T10:06:16-05:00)
Maven home: C:\AEM\apache-maven-3.6.2\bin\..
Java version: 1.8.0_271, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jdk1.8.0_271\jre
Default locale: en_US, platform encoding: Cp1252
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

来自:https://subscription.packtpub.com/book/application_development/9781785286124/1/ch01lvl1sec13/changing-the-jdk-used-by-maven