Gradle Java 9 支持状态

这篇文章概述了 Gradle 对 Java 9 的支持,涵盖了运行时、交叉编译、MRJAR 和 Jigsaw 模块支持。自从上个月 Java 9 发布以来,我们收到了很多问题,因此我们决定在这里回答。

Gradle 4.2.1 版本支持的内容

从 Gradle 4.2.1 开始,使用 Oracle JDK9、OpenJDK9 和 Azul JDK9 等主要 JDK 9 发行版构建和运行 Java 应用程序得到完全支持。此外,还支持交叉编译(由 JDK9 构建,但在 JDK8 上运行)。

无论使用什么构建工具,升级到 Java 9 时,某些构建都会中断。Java 团队对 JDK 做了一些必要且良好的更改,以促进更好的软件架构和安全性,但这意味着删除了对某些 API 的访问权限。即使您的项目已准备就绪,某些工具和 Gradle 插件尚未更新以支持 Java 9。

没有用于使用和组装多版本 JAR 的便捷方法,但如果您想使用它们,可以查看此 MRJAR-gradle 示例

Java 模块,也称为 Jigsaw 支持

如果您还不熟悉 Java 9 平台模块系统(也称为 Project Jigsaw),您应该阅读 Project Jigsaw: 模块系统快速入门指南。在 模块系统现状 中对动机和术语进行了很好的解释。

模块被定义为“代码和数据的命名、自描述集合”,其中包被视为代码边界,并被明确地导出要求。未导出的包对模块使用者不可见,此外,2 个模块不能导出相同的包,也不能具有相同的内部包。这意味着包不能在多个模块之间“拆分”或复制,否则编译将失败。

这里有一份指南,展示了如何在当今使用 Gradle 的 Java 模块。它将引导您完成必要的步骤,告诉 Gradle 在编译 Java 源代码和修补测试模块时使用 modulepath 而不是 classpath

如果您希望逐步转换为 Java 9 模块,建议采用自下而上的方法(首先转换没有依赖项的库)。毕竟,模块可以作为常规 JAR 使用。在将“传统”JAR 添加到 modulepath 时,请注意自动模块

使用 Java 库插件实现封装

Java 9 模块系统的两个主要目标之一是通过强大的封装提供更好的软件架构。Gradle 3.4 引入了Java 库插件,该插件通过将 api 依赖项(那些旨在向消费者公开的依赖项)与 implementation 依赖项(其内部不会泄露给消费者)分开,从而为库强制执行强大的封装。

当然,这不会消除 Java 类路径的使用,正如Java 模块的另一个目标所述。您可以在这篇文章中了解 Java 库插件的动机和用法。值得注意的是,Java 库插件对于使用 Java 7 及更高版本的项目很有用——您无需迁移到 Java 9 即可获得更强大的封装。

在实践中,给定此示例库,这意味着以下内容

apply plugin: 'java-library'

name = 'mylibrary'
group = 'com.mycompany'

dependencies {
   api project(':model')
   implementation 'com.google.guava:guava:18.0'
}

假设我们有一个使用 mylibrary 的应用程序。

public class MyApplication {
    
    public static void main(String... args) {
        // This does not compile using 'java-library' plugin
        Set<String> strings = com.google.common.collect.ImmutableSet.of("Hello", "Goodbye");
        
        // This compiles and runs
        Foo foo = com.mycompany.model.internal.Foo();
        
        // This also compiles and runs
        Class clazz = MyApplication.class.getClassLoader().loadClass("com.mycompany.model.internal.Foo");
        Foo foo = (Foo) clazz.getConstructor().newInstance();
    }
}

您可以看到,通过采用 Gradle 的 Java 库插件,您获得了一些好处。如果您要迁移到 Java 模块,可以使用此粗略映射

  • implementation 依赖项 => requires 模块声明
  • api 依赖项 => requires transitive 模块声明
  • runtimeOnly 依赖项 => requires static 模块声明

下一步

关注Gradle 中一流 Java 模块支持的更新。

您可以使用构建 Java 9 模块指南了解如何立即使用 Gradle 与 Java 模块。

讨论