Java 工具链介绍
引言
构建 Java 项目和运行 Gradle 都需要安装 JDK。大多数 Gradle 用户方便地使用运行 Gradle 的 Java 安装来构建和测试其应用程序。
虽然这在简单情况下是可以接受的,但这种方法存在一些问题。例如,如果构建要求在所有机器上使用相同的 Java 版本,则每个开发人员都需要了解该要求并手动安装该版本。
Gradle 已经可以配置为使用与运行 Gradle 所用 Java 版本不同的 Java 版本来构建项目。但是,这需要分别配置每个任务,如编译、测试和 javadoc。
Gradle 6.7 引入了“Java 工具链支持”。简而言之,它允许您使用已安装的任何 Java 版本运行 Gradle,而 Gradle 则使用在单个位置声明的 Java 版本构建项目。Gradle 将自动配置构建,检测已安装的 JDK,并在尚未安装的情况下下载所需的 JDK。
不再需要调整 release
或 sourceCompatibility
,也不再需要描述应为构建安装哪个 JDK 的 Wiki 页面。优点是巨大的,让我们看看如何使用它!
Java 工具链支持介绍 #
Java 工具链支持使构建作者能够声明其项目编译、测试和运行其代码所需的 Java 版本。
项目范围配置 #
让我们从您作为构建作者需要做的最少的事情开始
plugins {
id("java-library") // or id("application")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
就是这样!
使用 Gradle 6.7 中的上述配置,您会得到什么?
您会得到
- 所有 Java 编译任务都将使用 Java 11 进行构建。这意味着
main
和test
源代码集中的代码,以及您添加的任何自定义源代码集中的 Java 代码,都将使用配置的 Java 版本进行构建。 - 所有测试任务,包括默认的
test
任务和任何其他自定义Test
任务,都将使用 Java 11 运行测试。 javadoc
任务将使用 Java 11 构建文档。
此外,使用 application
插件,run
任务将使用 Java 11 启动您的应用程序。
在后台,Gradle 将会
- 从 已知位置 列表中找到 Java 11 安装,例如 asdf、jabba、SDKMAN! 或每个操作系统的标准位置
- 验证安装及其版本
- 如果未找到 Java 11 安装,Gradle 将尝试从 AdoptOpenJDK 下载一个
如果 Gradle 找不到请求的 Java 版本,您可以告诉它 在哪里查找。
任务级别配置 #
在某些情况下,您需要为特定任务使用不同的工具链。假设您开发的库具有取决于其运行的 Java 版本的特定代码路径。您将希望确保两个代码路径都已执行,因此将使用不同的 Java 版本运行一组测试。此场景支持如下。
tasks.register<Test>("extraTests") {
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(14))
})
}
请访问文档以了解更多信息。
工具链使用的更多好处 #
除了我们之前讨论的好处之外,工具链可以在更多情况下提供帮助。
Gradle 很难在尚未发布的 Java 版本(例如撰写本文时的 Java 16)上构建代码,这可能会导致现有版本的 Gradle(例如当前的 6.7 版本)无法运行。
借助工具链支持,Gradle 6.7 完全能够使用尚未发布的语言版本编译和测试代码。您只需要要求它这样做
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(16))
}
}
此外,代码在不同 Java 版本下构建和运行时可能表现不同,这可能会导致难以诊断的问题。
即使没有影响系统行为的不兼容性,在不同机器上使用不同的 Java 版本构建项目也会因为构建缓存未命中而降低构建性能。
放宽 Gradle 对 Java 版本的限制 #
除了对构建作者的好处之外,此功能还将影响 Gradle 本身的开发。到目前为止,Gradle 假定它将使用项目所需的相同 Java 版本运行。这意味着 Gradle 必须能够使用一组 Java 版本运行,以满足使用 Gradle 的项目的需求。随着 Java 5 到 8 的发布节奏,这可能是可以接受的。随着新的 Java 发布计划,这更成问题。
截至 6.7 版本,Gradle 要求
- 至少 Java 8 才能运行构建,
- 每日使用 11 构建
- 并测试到 Java 15。
所有这些都需要相当复杂的 CI 设置,并对 Gradle 核心开发施加限制。例如,Java 8 之外的功能和 API 对于 Gradle 工程师来说是不可用的,无法用于开发工具。
一旦社区采用工具链,我们最终将能够对 Gradle 的运行时要求放宽限制。Gradle 可能只在相对较新的 Java 版本上运行,同时通过工具链支持为旧 Java 版本构建代码。
工具链的下一步是什么? #
在 Gradle 6.7 中,工具链支持仅限于 Java 专用插件已知的任务
JavaCompile
Test
Javadoc
JavaExec
计划在下一个 Gradle 版本中为 Groovy 和 Scala 插件添加工具链支持。
我们还希望,鉴于此功能对用户的好处,社区插件作者将在其自己的任务中利用工具链支持。