Gradl支持下的Java 9的相关问题解决

105 阅读3分钟

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

从4.2.1版开始,Gradle支持什么?

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

在升级到Java 9时,无论使用何种构建工具,有些构建都会出现问题。Java团队对JDK进行了良好和必要的修改,以促进更好的软件架构和安全性,但这意味着取消对一些API的访问。即使你的项目已经准备好了,一些工具和Gradle插件还没有被更新以适应Java 9。

目前还没有消费和组装多版本JAR的便利方法,但如果你渴望使用它们,可以看看这个MRJAR-gradle的例子

Java模块,又称Jigsaw Support

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

一个模块被定义为 "一个命名的、自我描述的代码和数据的集合",其中包被视为代码边界,并被明确地导出要求。非出口的包对于模块消费者来说是不可见的,而且两个模块不能出口相同的包,也不能有相同的内部包。这意味着包不能被 "分割 "或在多个模块之间重复,否则编译会失败。

这里有一份指南,展示了今天如何用Gradle来使用Java模块。它引导你完成必要的步骤,告诉Gradle在编译Java源和补丁模块时使用modulepath ,而不是classpath ,以达到测试目的。

如果你想逐步转换到Java 9模块,建议采用自下而上的方法(先转换没有依赖关系的库)。毕竟,模块是可以像普通JAR一样消耗的。当 "传统的 "JARs被添加到modulepath ,要注意自动模块

用Java库插件实现封装

Java 9模块系统的2个主要目标之一是通过强封装提供更好的软件架构。Gradle 3.4引入了Java Library Plugin,它通过分离api (那些要暴露给消费者的)和implementation (其内部不会泄露给消费者)的依赖关系来实现对库的强封装。

当然,这并不排除使用Java classpaths,这是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 dependency => 模块声明requires
  • api 依赖性 => 模块声明requires transitive
  • runtimeOnly 依赖性 => 模块声明requires static

接下来的步骤

请继续关注Gradle中对第一类Java模块支持的更新。

你可以使用《构建Java 9模块》指南来学习如何使用Gradle的Java模块。