JavaFX 应用程序中 "maven-compiler-plugin" 的“<configuration>”上的“<release>”元素是什么

What is "<release>" element on "<configuration>" for the "maven-compiler-plugin" in a JavaFX app

我使用 org.openjfx:javafx-archetype-simple Maven 原型开始了我的第一个 JavaFX 项目。

生成的 POM:

<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example.invoicing</groupId>
    <artifactId>Invoicer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>14</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <release>14</release>   ???
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>0.0.4</version>
                <configuration>
                    <mainClass>com.example.invoicing.App</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

<configuration> 中的 <release>14</release> 行对于插件 <artifactId>maven-compiler-plugin</artifactId> 的用途是什么?

我找到了 Maven 编译器插件的文档,Compiling Your Java Sources。但它只提到<!-- put your configurations here -->。所以我对这里的具体配置选项一无所知。

<release>14</release>是用来编译的Java版本吗?它是 OpenJFX 的版本吗?还有别的吗?

我试过任意使用28。做一个 Maven > install 抛出了这个错误,并带有一条无用的错误消息,没有关于发布什么产品的线索:

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project Invoicer: Fatal error compiling

compile options 页面声明这最终作为传递给 javac-release 参数。

关于--release release

Compiles against the public, supported and documented API for a specific VM version. Supported release targets are 6, 7, 8, and 9.

据我了解,Java9 引入了一项功能,可帮助开发人员在最新的编译器上构建,针对较旧的运行时,但同时防止让代码编译时引用较新的旧问题针对旧运行时的 API。

参见:JEP 247: Compile for Older Platform Versions

示例:如果您使用 Java 8 编译使用新 Java 8 API(例如 Collection.stream())的代码,目标为 1.7,则此代码可以编译,但会在 Java 7 运行时失败并出现 NoSuchMethodError.

On JDK 9, if you use --release 1.7, the compiler will know that Collection.stream() can't be correctly targeted at Java 7 and will fail the build.

release标志相当于为编译器插件指定相同值的源和目标。自 Java-9.

以来,它支持 Java 编译器的 -release 参数
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>14</source>
        <target>14</target>
    </configuration>
</plugin>

注意:同理,可以去掉声明为

的冗余属性
<maven.compiler.source>14</maven.compiler.source>
<maven.compiler.target>14</maven.compiler.target>

进一步: | The -release flag in javac was introduced to Compile for Older Platform Versions.


完成您尝试将版本值设为 28 的部分的答案。使用 Maven 版本时 -

Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-05T00:30:29+05:30)

错误消息读得很清楚它应该是什么(如果你可以在问题中分享完整的日志)

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project forty-bits-of-java: 
Fatal error compiling: error: release version 28 not supported 

tl;博士

在您的 POM 中,替换两个标签 sourcetarget,如下所示:

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--The following `source` and  `target` tags are now replaced by `release` seen further down below.-->
        <!--<maven.compiler.source>14</maven.compiler.source>-->
        <!--<maven.compiler.target>14</maven.compiler.target>-->
    </properties>

…使用新的 release 标签,放置在 POM 的更下方:

<build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
        <plugins>
            …

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <!--Enable Java language preview features. Specify Java version.-->
                    <!--This `release` tag replaced the pair of `source` and  `target` tags seen commented-out near top of this POM.-->
                    <release>14</release>
                </configuration>
            </plugin>
…

…告诉Java 编译器您打算部署 的Java 版本。此标记将 release 标志传递给 Java 编译器。编译器会在您尝试使用添加到 Java.

更高版本的 API 的任何代码时出错

再看一个问题:

详情

两个答案 and 都是正确且重要的。但是我需要写这个答案来结合它们并展示直接的解决方案。

问题

问题是 JEP 247: Compile for Older Platform Versions 在 Java 9 中添加了一个新的编译器标志 -release 的特性来替换旧的 -source、[=23= 的组合] 和 -bootclasspath 标志。这填补了一个漏洞,这个漏洞困扰着试图在最新编译器上工作的程序员,同时编写仅限于对 Java.

的早期版本进行 API 调用的代码。

例如,我可能正在使用 Java 12 在我的 Mac 上编写,但部署到服务器 运行ning Java 8。我希望编译器停止我不小心使用了 Java 更高版本中的功能。否则,我的应用程序将在编译时成功,但在 运行 时失败,因为这些功能在较旧的 JVM.

上不可用

引用 JEP:

Summary

Enhance javac so that it can compile Java programs to run on selected older versions of the platform.

Motivation

javac provides two command line options, -source and -target, which can be used to select the version of the Java language accepted by the compiler and the version of the class files it produces, respectively. By default, however, javac compiles against the most-recent version of the platform APIs. The compiled program can therefore accidentally use APIs only available in the current version of the platform. Such programs cannot run on older versions of the platform, regardless of the values passed to the -source and -target options. This is a long-term usability pain point, since users expect that by using these options they'll get class files that can run on the the platform version specified by -target.

解决方案

Maven-driven project, we pass those flags to the Java compiler by setting tags on our Maven POM 文件中。

在您的 Maven POM 文件的标签层次结构中:

<project> …
    <build> …
        <pluginManagement> …
            <plugins> …
                <plugin> 
                    <artifactId>maven-compiler-plugin</artifactId>

…嵌套以下标签层次结构,我们在其中指定我们想要的 Java.

部署版本
<configuration> 
    <release>14</release>

顺便说一下,如果使用提供 "preview" features 的 Java 版本,如果我们希望启用这些预览功能,我们可以嵌套更多的标签和值。

<compilerArgs>--enable-preview</compilerArgs>

被新 release 标签取代的旧式设置是一对标签,sourcetarget。这两个可以在 Maven 中设置以传递给 Java 编译器。所以如果你添加上面看到的 release 标签,检查你的 POM 是否有这对标签。如果找到,请删除它们。

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>14</maven.compiler.source>   Delete if using `release` tag.
    <maven.compiler.target>14</maven.compiler.target>   Delete if using `release` tag.
</properties>

示例 POM 文件

这是 Maven 3.6.3 的完整示例 POM 文件,用于基本 Java 项目。

我们使用的是各种插件和依赖项的所有最新版本。此示例使用 Java 15 with preview features such as Records 启用。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>work.basil.demo</groupId>
    <artifactId>Demo5</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>Demo5</name>
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--The following `source` and  `target` tags are now replaced by `release` seen further down below.-->
        <!--<maven.compiler.source>15</maven.compiler.source>-->
        <!--<maven.compiler.target>15</maven.compiler.target>-->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.7.0-M1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>

                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <!--Enable Java language preview features. Specify Java version.-->
                        <!--This `release` tag replaced the pair of `source` and  `target` tags seen commented-out near top of this POM.-->
                        <release>15</release>
                        <compilerArgs>
                            --enable-preview
                        </compilerArgs>
                    </configuration>
                </plugin>

                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M4</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.2.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>3.0.0-M1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>3.0.0-M1</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.8.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

Java外汇

您在问题中提到了 JavaFX。请注意,此讨论适用于所有 Maven 驱动的 Java 项目。这包括 JavaFX 项目以及 Jakarta Servlets、控制台应用程序等。这里没有什么是 JavaFX 特有的。