守護進程是一個電腦程式,它作為背景程序運行,而不是在互動使用者的直接控制下。

Gradle 在 Java 虛擬機 (JVM) 上運行,並使用多個支援庫,這些庫具有非平凡的初始化時間。啟動可能很慢。Gradle 守護進程解決了這個問題。

Gradle 守護進程是一個長期運行的背景程序,它可以減少運行建置所需的時間。

Gradle 守護進程通過以下方式減少建置時間:

  • 跨建置快取專案資訊

  • 在背景運行,因此每次 Gradle 建置都不必等待 JVM 啟動

  • 受益於 JVM 中的持續運行時最佳化

  • 監控檔案系統,以準確計算在運行建置之前需要重建的內容

了解守護進程

Gradle JVM 客戶端將守護進程建置資訊(例如命令列引數、專案目錄和環境變數)發送給守護進程,以便它可以運行建置。守護進程負責解析依賴關係、執行建置腳本、建立和運行任務;完成後,它會將輸出發送給客戶端。客戶端和守護進程之間的通訊通過本地套接字連線進行。

守護進程使用 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 版本如何,請參閱尋找守護進程

配置守護進程 JVM

守護進程 JVM 探索和條件是孵化中的功能,並且在未來的版本中可能會有所變更。

預設情況下,Gradle 守護進程使用啟動建置的相同 JVM 安裝運行。Gradle 預設為當前 shell 路徑和 JAVA_HOME 環境變數以尋找可用的 JVM。

或者,可以使用org.gradle.java.home Gradle 屬性或通過 Tooling API 以編程方式為建置指定不同的 JVM 安裝。

基於工具鏈功能,您現在可以使用宣告式條件來指定建置的 JVM 需求。

如果提供了守護進程 JVM 條件配置,則它優先於 JAVA_HOMEorg.gradle.java.home

守護進程 JVM 條件

守護進程 JVM 條件updateDaemonJvm 任務控制,類似於wrapper 任務更新 wrapper 屬性檔案的方式。

此過程需要配置工具鏈下載儲存庫。有關詳細資訊,請參閱下方

當任務運行時,它會在 gradle/gradle-daemon-jvm.properties 檔案中建立或更新條件。

要配置生成,您可以使用命令列選項

$ ./gradlew updateDaemonJvm --jvm-version=17

或在根專案的建置腳本中配置任務

build.gradle.kts
tasks.named<UpdateDaemonJvm>("updateDaemonJvm") {
    languageVersion = JavaLanguageVersion.of(17)
}
build.gradle
tasks.named("updateDaemonJvm") {
    languageVersion = JavaLanguageVersion.of(17)
}

然後運行任務

$ ./gradlew updateDaemonJvm

這兩個動作都將產生如下檔案

gradle/gradle-daemon-jvm.properties
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://example.com/...
toolchainUrl.FREE_BSD.X86_64=https\://example.com/...
toolchainUrl.LINUX.AARCH64=https\://example.com/...
toolchainUrl.LINUX.X86_64=https\://example.com/...
toolchainUrl.MAC_OS.AARCH64=https\://example.com/...
toolchainUrl.MAC_OS.X86_64=https\://example.com/...
toolchainUrl.UNIX.AARCH64=https\://example.com/...
toolchainUrl.UNIX.X86_64=https\://example.com/...
toolchainUrl.WINDOWS.X86_64=https\://example.com/...
toolchainVersion=17

如果您在沒有任何引數的情況下運行 updateDaemonJvm 任務,並且屬性檔案不存在,則將使用守護進程使用的當前 JVM 版本。

在下次執行建置時,Gradle 客戶端將使用此檔案來尋找相容的 JVM 安裝並使用它啟動守護進程。

與 wrapper 類似,生成的 gradle-daemon-jvm.properties 檔案應簽入版本控制。這可確保任何開發人員或 CI 伺服器運行建置都將使用相同的 JVM 版本。

指定 JVM 供應商

JVM 供應商(如 JVM 版本)可以用作選擇與建置相容的 JVM 安裝的條件。如果未指定供應商,Gradle 會認為所有供應商都相容。

預設情況下,運行 updateDaemonJvm 以建立 gradle-daemon-jvm.properties 檔案不會生成 JVM 供應商條件。要指定供應商,請在建置腳本中配置它,使用與 Java 工具鏈規範相同的語法,或在命令列中傳遞它

$ ./gradlew updateDaemonJvm --jvm-version=17 --jvm-vendor=adoptium

已識別供應商列表

已知供應商 可接受的字串 toolchainVendor

Adoptium / Eclipse Temurin

adoptium, temurin, eclipse foundation

ADOPTIUM

AdoptOpenJDK

adoptopenjdk, aoj

ADOPTOPENJDK

Amazon Corretto

amazon, corretto

AMAZON

Apple

apple

APPLE

Azul Zulu

azul, zulu

AZUL

BellSoft

bellsoft, liberica

BELLSOFT

GraalVM

graalvm, graal vm

GRAAL_VM

Hewlett Packard

hp, hewlett

HEWLETT_PACKARD

IBM

ibm, semeru, international business machines corporation

IBM

JetBrains

jetbrains, jbr

JETBRAINS

Microsoft

microsoft

MICROSOFT

Oracle

oracle

ORACLE

SAP

sap

SAP

Tencent

tencent, kona

TENCENT

某些供應商將從多個字元集中識別。所有供應商字串都不區分大小寫。您可以通過運行 ./gradlew help --task updateDaemonJvm 來檢視已識別供應商的列表。

如果指定的供應商不是已識別的等效項之一,Gradle 將完全匹配它。例如,「MyCustomJVM」將需要供應商名稱的完全匹配。

自動偵測和自動配置

守護進程 JVM 使用與專案 JVM 工具鏈相同的邏輯進行自動偵測

通過自動配置,邏輯更簡單,因為 Gradle 只能在 gradle-daemon-jvm.properties 檔案中查找與平台匹配的下載 URL。如果本地找不到 JDK,則 URL 用於下載 JDK。

用於停用自動偵測自動配置的屬性會影響守護進程工具鏈解析邏輯

org.gradle.java.installations.auto-detect=false
org.gradle.java.installations.auto-download=false

配置配置 URL

目前沒有用於配置此項的 CLI 選項。

預設情況下,updateDaemonJvm 任務嘗試為與指定條件匹配的各種平台(作業系統和架構)上的 JDK 生成下載 URL。Gradle 需要考慮的不僅僅是當前運行的平台,因為建置可能會在不同的平台上運行。

Gradle 根據架構 X86_64AARCH64 為以下作業系統設定慣例建置平台

這些平台可以通過 UpdateDaemonJvm 任務的 toolchainPlatforms 屬性進行配置。

build.gradle.kts
tasks.named<UpdateDaemonJvm>("updateDaemonJvm") {
    val myPlatforms = mutableListOf(
        BuildPlatformFactory.of(
            org.gradle.platform.Architecture.AARCH64,
            org.gradle.platform.OperatingSystem.MAC_OS
        )
    )
    toolchainPlatforms.set(myPlatforms)
}
build.gradle
tasks.named("updateDaemonJvm") {
    def myPlatforms = [
        BuildPlatformFactory.of(
            org.gradle.platform.Architecture.AARCH64,
            org.gradle.platform.OperatingSystem.MAC_OS
        )
    ]
    toolchainPlatforms.set(myPlatforms)
}

Gradle 通過使用配置的工具鏈下載儲存庫來解析這些平台的 JDK 下載 URL。如果未配置此類儲存庫,並且 toolchainPlatforms 屬性至少有一個值,則 updateDaemonJvm 任務將失敗。

或者,使用者可以使用 toolchainDownloadUrls 屬性直接配置特定平台的 JDK URL。此屬性是一個 Map<BuildPlatform, URI>,可以按以下範例所示進行配置

build.gradle.kts
tasks.named<UpdateDaemonJvm>("updateDaemonJvm") {
    toolchainDownloadUrls = mapOf(
        BuildPlatformFactory.of(org.gradle.platform.Architecture.AARCH64, org.gradle.platform.OperatingSystem.MAC_OS) to uri("https://server?platform=MAC_OS.AARCH64"),
        BuildPlatformFactory.of(org.gradle.platform.Architecture.AARCH64, org.gradle.platform.OperatingSystem.WINDOWS) to uri("https://server?platform=WINDOWS.AARCH64")
    )
}
build.gradle
tasks.named("updateDaemonJvm") {
    toolchainDownloadUrls = [(BuildPlatformFactory.of(org.gradle.platform.Architecture.AARCH64, org.gradle.platform.OperatingSystem.MAC_OS)) : uri("https://server?platform=MAC_OS.AARCH64"),
                             (BuildPlatformFactory.of(org.gradle.platform.Architecture.AARCH64, org.gradle.platform.OperatingSystem.WINDOWS)) : uri("https://server?platform=WINDOWS.AARCH64")]
}
由於與不同套件中的其他類型命名衝突,完整套件名稱是 org.gradle.platform.Architectureorg.gradle.platform.OperatingSystem 所必需的,這些類型首先按字母順序解析。

運行 ./gradlew updateDaemonJvm 會產生以下內容

gradle/gradle-daemon-jvm.properties
#This file is generated by updateDaemonJvm
toolchainUrl.MAC_OS.AARCH64=https\://server?platform\=MAC_OS.AARCH64
toolchainUrl.WINDOWS.AARCH64=https\://server?platform\=WINDOWS.AARCH64
toolchainVersion=17

如果您想停用 updateDaemonJvm 任務生成 URL

build.gradle.kts
tasks.named<UpdateDaemonJvm>("updateDaemonJvm") {
    toolchainDownloadUrls.empty()
}
build.gradle
tasks.named("updateDaemonJvm") {
    toolchainPlatforms = []
}

刪除所有平台意味著不再需要配置工具鏈下載儲存庫

工具和 IDE

IDE 和其他工具用於與 Gradle 集成的 Gradle Tooling 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%。

在建置之間,守護進程會閒置等待下一個建置。因此,您的機器僅為多個建置將 Gradle 加載到記憶體一次,而不是每次建置一次。這是一個顯著的效能最佳化。

運行時程式碼最佳化

JVM 從運行時程式碼最佳化中獲得顯著效能:應用於程式碼的優化,同時程式碼正在運行。

JVM 實作(如 OpenJDK 的 Hotspot)在執行期間逐步最佳化程式碼。因此,後續建置可以更快,純粹是因為此最佳化過程。

使用守護進程,專案的第 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