守护程序是一种计算机程序,它作为后台进程运行,而不是受交互式用户的直接控制.
—维基百科

Gradle在Java虚拟机(JVM)上运行,并使用几个支持库,它们需要很短的初始化时间. 结果,有时启动似乎有些慢. 解决此问题的方法是Gradle Daemon :这是一个长期存在的后台进程,与以前相比,它可以更快地执行构建. 通过避免昂贵的引导过程以及利用缓存(将有关项目的数据保留在内存中),我们可以实现这一目标. 使用Daemon运行Gradle构建与没有运行没有什么不同. 只需配置您是否要使用它-其他所有事情都由Gradle透明地处理.

Why the Gradle Daemon is important for performance

守护进程是一个长期存在的过程,因此我们不仅可以避免每次构建都需要启动JVM的成本,而且还可以在内存中缓存有关项目结构,文件,任务等的信息.

推理很简单:通过重用以前构建的计算来提高构建速度. 但是,这样做的好处是巨大的:我们通常会在以后的构建中将构建时间减少15-75%. 我们建议您使用--profile对构建进行概要分析,以了解Gradle Daemon对您的影响.

默认情况下,Gradle Daemon从Gradle 3.0开始启用,因此您无需做任何事情就可以从中受益.

Running Daemon Status

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

样本输出:

    PID VERSION                 STATUS
  28411 3.0                     IDLE
  34247 3.0                     BUSY

当前,给定的Gradle版本只能连接到相同版本的守护程序. 这意味着状态输出将仅显示正在调用的Gradle版本的守护程序,而不显示任何其他版本的守护程序. Gradle的未来版本将解除此约束,并将显示所有Gradle版本的正在运行的守护程序.

Disabling the Daemon

Gradle守护程序默认情况下处于启用状态,我们建议始终启用它. 有几种方法可以禁用守护程序,但是最常见的一种方法是添加该行

org.gradle.daemon=false

到文件«USER_HOME»/.gradle/gradle.properties ,其中«USER_HOME»是您的主目录. 通常是以下之一,具体取决于您的平台:

  • C:\Users\<username> (Windows Vista和7+)

  • /Users/<username> (macOS)

  • /home/<username> (Linux)

如果该文件不存在,请使用文本编辑器创建它. 您可以在下面的" 守护程序常见问题"中找到其他禁用(启用)守护程序的方法的详细信息. 该部分还包含有关守护程序如何工作的更多详细信息.

请注意,启用了守护程序后,无论特定构建使用的Gradle版本如何,所有构建都将利用速度提升.

💡
持续集成

从Gradle 3.0开始,我们默认启用Daemon并建议将其用于开发人员的计算机和Continuous Integration服务器. 但是,如果您怀疑Daemon使CI构建不稳定,则可以将其禁用以对每个构建使用全新的运行时,因为运行时与任何先前的构建完全隔离.

Stopping an existing Daemon

如前所述,守护进程是一个后台进程. 不过,您不必担心计算机上会建立Gradle进程. 与可用的系统内存总量相比,每个守护程序都会监视其内存使用情况,如果可用系统内存不足,则每个空闲进程都会在空闲时停止运行. 如果出于任何原因要显式停止运行Daemon进程,只需使用命令gradle --stop .

这将终止所有与用于执行命令的相同Gradle版本一起启动的Daemon进程. 如果安装了Java开发工具包(JDK),则可以通过运行jps命令轻松地验证守护程序是否已停止. 您将看到所有正在运行的名称为GradleDaemon守护程序.

FAQ

How do I disable the Gradle Daemon?

有两种建议的方法可以持久禁用环境的守护程序:

  • 通过环境变量:将标志-Dorg.gradle.daemon=false添加到GRADLE_OPTS环境变量

  • 通过属性文件:将org.gradle.daemon=false添加到«GRADLE_USER_HOME»/gradle.properties文件中

注意, «GRADLE_USER_HOME»默认为«USER_HOME»/.gradle ,其中«USER_HOME»是当前用户的主目录. 可以通过-g--gradle-user-home命令行开关以及GRADLE_USER_HOME环境变量和org.gradle.user.home JVM系统属性来配置此位置.

两种方法具有相同的效果. 使用哪一个取决于个人喜好. 大多数Gradle用户选择第二个选项,并将条目添加到用户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

一旦以这种方式为构建环境禁用了守护程序,除非使用--daemon选项明确请求,否则不会启动Gradle守护程序.

--daemon--no-daemon命令行选项启用和个人的构建调用的守护进程的禁止使用使用摇篮命令行界面时. 在考虑构建环境时,这些命令行选项具有最高优先级. 通常,为环境(例如用户帐户)启用守护程序更为方便,以便所有构建都使用守护程序,而无需记住提供--daemon选项.

Why is there more than one Daemon process on my machine?

There are several reasons why Gradle will create a new Daemon, instead of using one that is already running. The basic rule is that Gradle will start a new Daemon if there are no existing idle or compatible Daemons available. Gradle will kill any Daemon that has been idle for 3 hours or more, so you don’t have to worry about cleaning them up manually.

idle

空闲的守护程序是当前未执行构建或未执行其他有用工作的守护程序.

compatible

兼容的守护程序是可以(或可以使其)满足所请求构建环境的要求的守护程序. 用于执行构建的Java运行时是构建环境的一个示例方面. 另一个示例是构建运行时所需的JVM系统属性集.

守护程序可能无法满足请求的构建环境的某些方面. 如果守护程序与Java 8运行时一起运行,但是请求的环境要求Java 10,则该守护程序不兼容,必须启动另一个守护程序. 而且,一旦JVM启动,就无法更改Java运行时的某些属性. 例如,不可能更改正在运行的JVM的内存分配(例如-Xmx1024m ),默认文本编码,默认语言环境等.

通常从构建客户端(例如Gradle命令行客户端,IDE等)环境的各个方面隐式构建"请求的构建环境",并通过命令行开关和设置显式构建"请求的构建环境". 有关如何指定和控制构建环境的详细信息,请参见构建环境.

以下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参数)

所需的Gradle版本是所请求的构建环境的另一方面. 守护进程与特定的Gradle运行时耦合. 在使用不同Gradle版本的会话中处理多个Gradle项目是导致多个Daemon进程运行的常见原因.

How much memory does the Daemon use and can I give it more?

如果请求的构建环境未指定最大堆大小,则守护程序将使用最多512MB的堆. 它将使用JVM的默认最小堆大小. 对于大多数构建来说,512MB绰绰有余. 具有数百个子项目的较大内部版本,大量配置和源代码可能需要或具有更好的性能,并具有更多的内存.

要增加守护程序可以使用的内存量,请在请求的构建环境中指定适当的标志. 有关详细信息,请参见Build Environment .

How can I stop a Daemon?

闲置3个小时或更短的时间后,守护进程将自动终止. 如果您希望在此之前停止Daemon进程,则可以通过操作系统终止该进程或运行gradle --stop命令. --stop开关使Gradle请求所有正在运行的,与用于运行命令的Gradle版本相同的 Daemon进程自行终止.

What can go wrong with Daemon?

在日常开发中,使Daemon健壮,透明且不引人注目的工程已经投入了大量精力. 但是,守护进程有时会被破坏或耗尽. Gradle构建从多个源执行任意代码. 虽然Gradle本身是为Daemon设计并经过严格测试的,但用户生成脚本和第三方插件可能会通过内存泄漏或全局状态损坏等缺陷破坏Daemon进程的稳定性.

通过运行无法正确释放资源的构建,还可能破坏守护程序的稳定性(通常是构建环境). 当使用Microsoft Windows时,这是一个特别棘手的问题,因为它对读取或写入后无法关闭文件的程序的宽容度较小.

Gradle主动监视堆使用情况,并尝试检测何时泄漏开始耗尽守护程序中的可用堆空间. 当检测到问题时,Gradle守护程序将完成当前正在运行的构建,并在下一个构建中主动重新启动该守护程序. 默认情况下启用此监视,但是可以通过将org.gradle.daemon.performance.enable-monitoring系统属性设置为false来禁用此监视.

如果怀疑Daemon进程变得不稳定,则可以将其杀死. 回想一下,可以为构建指定--no-daemon开关,以防止使用守护程序. 这对于诊断守护程序是否实际上是问题的元凶很有用.

Tools & IDEs

IDE和其他工具用于与Gradle集成的Gradle Tooling API 始终使用Gradle守护程序来执行构建. 如果要在IDE中执行Gradle构建,则使用的是Gradle Daemon,而无需为您的环境启用它.

How does the Gradle Daemon make builds faster?

Gradle守护程序是一个长期存在的构建过程. 在两次构建之间,它空闲地等待下一次构建. 这具有明显的好处,即对于多个构建只需要一次将Gradle加载到内存中,而不是对于每个构建一次. 这本身就是一项重大的性能优化,但并非止于此.

对于现代JVM性能而言,故事的重要部分是运行时代码优化. 例如,HotSpot(Oracle提供的JVM实现,用作OpenJDK的基础)在运行时对代码进行优化. 优化是渐进的,不是瞬时的. 也就是说,在执行过程中对代码进行了逐步优化,这意味着纯粹由于此优化过程而使得后续构建可以更快. 使用HotSpot进行的实验表明,需要5到10次构建才能稳定优化. 守护程序的第一个构建和第10个构建之间的可感知构建时间差异可能非常明显.

守护程序还允许跨构建更有效地进行内存缓存. 例如,构建所需的类(例如,插件,构建脚本)可以保存在构建之间的内存中. 同样,Gradle可以维护构建数据的内存缓存,例如用于增量构建的任务输入和输出的哈希值.