如何在 jigsaw 和 jre 8 支持下使用 maven?

How to use maven with both jigsaw and jre 8 support?

我正在使用 Maven 构建一个 java 项目。 我想确定几件事:

  1. 构建的 jar 可以在 jre8 上 运行。
  2. 构建的 jar 可以在 jre9 上 运行,module/jigsaw。
  3. 构建的jar可以放在maven central上。

我应该如何配置maven-compiler-plugin? 谢谢。

原始仓库位于 https://github.com/cyanpotion/SDL_GameControllerDB_Util

现在我可以通过 2 和 3,但输出 jar 似乎不能 运行 在 jre8 上。

一个multi-release jar可以用来完成这个目的;但是,如果您仅在 Jigsaw 模块支持之后,Java 8 和 9 以及 maven-compiler-plugin 的双编译配置就足够了(如下所示)。

以下是能够保持 JRE 8 支持但兼容在 JRE 9+ 中用作模块的构建配置。如有必要,可以对其进行调整以支持最早可追溯到 JRE 1.6 的项目。

以下构建配置概述

  • 强制执行 $JAVA_HOME JDK 9+ 以便 module-info.java 可以根据源代码进行编译和验证(确保正确引用所有模块依赖项)。
  • default-compile 执行更改为 NO-OP。通过指定 <release>8</release>(或 target/source 标志),Maven auto-importation(使用 IntelliJ 测试)期间的某些 IDEs 将采用该项目的语言级别是 Java 8,并产生有关项目的 module-info.java.
  • 的错误
  • 为 Java 9 编译所有源代码(包括 module-info.java);这确保了 module-info.java 包含在没有项目源的情况下使用的任何依赖项。
  • 为Java8编译所有源代码(不包括module-info.java),覆盖所有以前编译的Java9classes Java 8 classes;这意味着唯一的 Java 9 class(class 53+ 级)将是 module-info.class。所有其他 classes 现在应该可以在兼容的 JRE 8 上执行。

备注:

  • 需要注意的是,这将编译源代码 两次 ,一次用于 Java 8,另一次用于 Java 9。这可能会显着增加更大的构建时间项目(但对于较小的项目可以忽略不计)。这可以通过将 module-info.java 放在另一个源目录(例如 src/main/java9)并配置 multi-release JAR(请参阅本消息开头的第一个 link)来解决。请注意,为了正确 IDE auto-importation 并正确标记此额外的 Java 9 源目录,可以使用带有 org.codehaus.mojo:build-helper-maven-plugin 的 NO-OP 执行。
  • 只有 module-info.java 将支持 Java 9,所有其他 class 仅限 classes/methods/fields/code 在 JDK/JRE 8 中可用。
  • 如果某些工具不支持 Java 9 module-info.class,则可能需要在您的项目配置中对其进行更新。默认 Maven 插件的一些旧变体对模块的支持不足。
<build>
    <plugins>
        <!-- ensure the project is compiling with JDK 9+ -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <version>3.0.0-M3</version>
            <executions>
                <execution>
                    <id>enforce-jdk9</id>
                    <goals>
                        <goal>enforce</goal>
                    </goals>
                    <configuration>
                        <rules>
                            <requireJavaVersion>
                                <version>[1.9,)</version>
                                <message>JDK 9+ is required for compilation</message>
                            </requireJavaVersion>
                        </rules>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <!-- compile sources -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <executions>
                <!-- disable default phase due to fixed id and position in lifecycle -->
                <execution>
                    <id>default-compile</id>
                    <phase>none</phase>
                    <!-- specify source/target for IDE integration -->
                    <configuration>
                        <release>9</release>
                    </configuration>
                </execution>
                <!-- compile sources with Java 9 to generate and validate module-info.java -->
                <execution>
                    <id>java-9-module-compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <release>9</release>
                    </configuration>
                </execution>
                <!-- recompile sources as Java 8 to overwrite Java 9 class files, except module-info.java -->
                <execution>
                    <id>java-8-compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <!-- specify JDK 9+ release flag to ensure no classes/methods later than Java 8 are used accidentally -->
                        <release>8</release>
                        <!-- exclude module-info.java from the compilation, as it is unsupported by Java 8 -->
                        <excludes>
                            <exclude>module-info.java</exclude>
                        </excludes>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

我做到了。查看我的项目,the IPAddress Java library。您使用 Java 9 编译器级别进行编译,然后使用 Java 8 编译级别重新编译除 module-info.java 之外的所有内容。所以您有一个 Java 8带有 Java 9 module-info 的罐子。您可以在 GitHub.

上的我的 ant xml 脚本中看到编译命令

最初 Android studio 有一个问题,现在已经解决了,不会忽略 module-info。最近的 Android 工作室版本很好,所有 Java 平台和环境也很好。 Java 9 jres 及以上会识别 module-info,Java 8 不会,Java 8 及更早版本将忽略它。

我的jar也在maven central里面,满足你的3个要求。使用 Java 8 或更高版本的 jres.

在您的开发环境中试用它以查看它是否有效

Multi-release 罐子不是必需的,不值得麻烦。

当我研究同样的问题时,我发现 Apache 项目正在使用同样的解决方案,所以我不是唯一一个这样做的人。