守护进程是作为后台进程运行的计算机程序,而不是直接由交互式用户控制。

Gradle 在 Java 虚拟机 (JVM) 上运行,并使用几个支持库,这些库的初始化时间不短。启动速度可能很慢。**Gradle 守护进程**解决了这个问题。

Gradle 守护进程是一个长生命周期的后台进程,可以减少运行构建所需的时间。

Gradle 守护进程通过以下方式减少构建时间:

  • 跨构建缓存项目信息

  • 在后台运行,因此每次 Gradle 构建都不必等待 JVM 启动

  • 从 JVM 中的持续运行时优化中受益

  • 监视文件系统 以计算在运行构建之前需要重建的内容

了解守护进程

Gradle JVM 客户端将构建信息(例如命令行参数、项目目录和环境变量)发送到守护进程,以便它可以运行构建。Wrapper 负责解析依赖项、执行构建脚本、创建和运行任务;完成后,它将输出发送到客户端。客户端和守护进程之间的通信通过本地套接字连接进行。

守护进程使用 JVM 的默认最小堆大小。

如果请求的构建环境没有指定最大堆大小,则守护进程使用最多 512MB 的堆。512MB 足够大多数构建。具有数百个子项目、配置和源代码的较大型构建可能会从更大的堆大小中受益。

检查守护进程状态

要获取正在运行的守护进程及其状态列表,请使用--status命令

$ gradle --status
   PID STATUS   INFO
 28486 IDLE     7.5
 34247 BUSY     7.5

目前,给定的 Gradle 版本只能连接到相同版本的守护进程。这意味着状态输出仅显示使用与当前项目相同的 Gradle 版本生成的守护进程。

查找守护进程

如果您已安装 Java 开发工具包 (JDK),则可以使用jps命令查看实时守护进程。

$ jps
33920 Jps
27171 GradleDaemon
22792

实时守护进程显示为GradleDaemon。由于此命令使用 JDK,因此您可以查看运行任何版本的 Gradle 的守护进程。

启用守护进程

从 Gradle 3.0 开始,Gradle 默认启用守护进程。如果您的项目未使用守护进程,则可以在运行构建时使用--daemon标志为单个构建启用它

$ gradle <task> --daemon

此标志会覆盖项目或用户gradle.properties文件中禁用守护进程的任何设置。

要在较旧的 Gradle 版本中默认启用守护进程,请将以下设置添加到项目根目录或 Gradle 用户主目录 (GRADLE_USER_HOME) 中的gradle.properties文件

gradle.properties
org.gradle.daemon=true

禁用守护进程

您可以通过多种方式禁用守护进程,但有一些重要的注意事项

单次使用守护进程

如果客户端进程的 JVM 参数与构建要求不匹配,则会创建一个单次使用守护进程(一次性 JVM)。这意味着构建需要守护进程,因此它会在构建结束时创建、使用,然后停止。

无守护进程

如果JAVA_OPTSGRADLE_OPTSorg.gradle.jvmargs匹配,则根本不会使用守护进程,因为构建发生在客户端 JVM 中。

为构建禁用

要为单个构建禁用守护进程,请在运行构建时传递--no-daemon标志

$ gradle <task> --no-daemon

此标志会覆盖项目中启用守护进程的任何设置,包括gradle.properties文件。

为项目禁用

要为项目的全部构建禁用守护进程,请将org.gradle.daemon=false添加到项目根目录中的gradle.properties文件。

为用户禁用

在 Windows 上,此命令会禁用当前用户的守护进程。

(if not exist "%USERPROFILE%/.gradle" mkdir "%USERPROFILE%/.gradle") && (echo. >> "%USERPROFILE%/.gradle/gradle.properties" && echo org.gradle.daemon=false >> "%USERPROFILE%/.gradle/gradle.properties")

在类 UNIX 操作系统上,以下 Bash shell 命令会禁用当前用户的守护进程。

mkdir -p ~/.gradle && echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties

全局禁用

有两种推荐的方法可以全局禁用环境中的守护进程。

  • org.gradle.daemon=false 添加到 $GRADLE_USER_HOME/gradle.properties` 文件中。

  • 将标志 -Dorg.gradle.daemon=false 添加到 GRADLE_OPTS 环境变量中。

不要忘记确保你的 JVM 参数和 GRADLE_OPTS / JAVA_OPTS 匹配,如果你想完全禁用守护进程,而不是仅仅调用一次性守护进程。

停止守护进程

在排查或调试故障时,停止守护进程可能会有所帮助。

在以下任何条件下,守护进程会自动停止。

  • 可用系统内存不足。

  • 守护进程已空闲 3 小时。

要停止运行的守护进程,请使用以下命令。

$ gradle --stop

这将终止所有使用与执行命令相同的 Gradle 版本启动的守护进程。

你也可以使用操作系统手动杀死守护进程。要查找所有守护进程的 PID(无论 Gradle 版本如何),请参阅 查找守护进程

工具和 IDE

IDE 和其他工具用来与 Gradle 集成的 Gradle 工具 API 始终 使用 Gradle 守护进程来执行构建。如果你从 IDE 中执行 Gradle 构建,那么你已经在使用 Gradle 守护进程。无需为你的环境启用它。

持续集成

我们建议在开发人员机器和持续集成 (CI) 服务器上使用守护进程。

兼容性

如果不存在空闲或兼容的守护进程,Gradle 会启动一个新的守护进程。

以下值决定了兼容性。

  • 请求的构建环境,包括以下内容。

    • Java 版本。

    • JVM 属性。

    • JVM 属性。

  • Gradle 版本。

兼容性基于这些值的精确匹配。例如。

  • 如果有一个使用 Java 8 运行时的守护进程可用,但请求的构建环境需要 Java 10,那么该守护进程不兼容。

  • 如果有一个运行 Gradle 7.0 的守护进程可用,但当前构建使用 Gradle 7.4,那么该守护进程不兼容。

Java 运行时的某些属性是不可变的:一旦 JVM 启动,它们就不能更改。以下 JVM 系统属性是不可变的

  • file.encoding

  • user.language

  • user.country

  • user.variant

  • java.io.tmpdir

  • javax.net.ssl.keyStore

  • javax.net.ssl.keyStorePassword

  • javax.net.ssl.keyStoreType

  • javax.net.ssl.trustStore

  • javax.net.ssl.trustStorePassword

  • javax.net.ssl.trustStoreType

  • com.sun.management.jmxremote

以下由启动参数控制的 JVM 属性也是不可变的

  • 最大堆大小(-Xmx JVM 参数)

  • 最小堆大小(-Xms JVM 参数)

  • 引导类路径(-Xbootclasspath 参数)

  • “断言”状态(-ea 参数)

如果这些属性和属性的任何一个所需的构建环境要求与守护进程的 JVM 要求不同,则守护进程不兼容。

有关构建环境的更多信息,请参阅构建环境文档

性能影响

当您重复构建同一个项目时,守护进程可以将构建时间减少 15-75%。

要了解守护进程对构建的影响,您可以使用 --profile 对构建进行分析。

在构建之间,守护进程会空闲等待下一个构建。因此,您的机器只会在多个构建中将 Gradle 加载到内存中一次,而不是每次构建一次。这是一个重大的性能优化。

运行时代码优化

JVM 从运行时代码优化中获得了显著的性能提升:在代码运行时应用的优化。

像 OpenJDK 的 Hotspot 这样的 JVM 实现会在执行期间逐步优化代码。因此,后续构建可能纯粹由于此优化过程而更快。

使用守护进程,项目的第 1 次和第 10 次构建之间的感知构建时间可能会大幅下降。

内存缓存

守护进程允许在构建之间进行内存中缓存。这包括插件和构建脚本的类。

同样,守护进程维护构建数据的内存缓存,例如增量构建的任务输入和输出的哈希值。

性能监控

Gradle 积极监控堆使用情况,以检测守护进程中的内存泄漏。

当内存泄漏耗尽可用堆空间时,守护进程

  1. 将完成当前正在运行的构建。

  2. 在运行下一个构建之前重新启动。

Gradle 默认启用此监控。

要禁用此监控,请将 org.gradle.daemon.performance.enable-monitoring 守护进程选项设置为 false

您可以在命令行中使用以下命令执行此操作

$ gradle <task> -Dorg.gradle.daemon.performance.enable-monitoring=false

或者您可以在项目根目录或您的 GRADLE_USER_HOME(Gradle 用户主目录)中的 gradle.properties 文件中配置此属性

gradle.properties
org.gradle.daemon.performance.enable-monitoring=false