You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自托管GitHub工作流中复用Gradle守护进程

GitHub Actions自托管Windows Runner中Gradle守护进程无法复用的解决方法

问题描述

每次运行GitHub工作流的Gradle构建步骤时,都会出现如下提示:

Starting a Gradle Daemon, 1 incompatible and 13 stopped Daemons could not be reused, use --status for details

每次构建都会启动新的Gradle守护进程,无法复用空闲进程。当前使用Windows自托管Runner,可修改脚本和环境的任何配置,需要解决两个问题:

  1. 如何实现空闲守护进程的复用?
  2. 为何同一项目之前的守护进程会被标记为“不兼容”?

工作流脚本如下(功能:推送main分支时检查版本号变更,若版本与最新标签不匹配则创建新Release):

name: Release

on:
  push:
    branches:
      - main

jobs:
  release:
    runs-on: self-hosted

    steps:
      - name: Checkout code
        run: |
          git fetch
          git pull

      - name: Set up JDK
        uses: actions/setup-java@v3.13.0
        with:
          distribution: 'adopt'
          java-version: '21'

      - name: Build and test
        run: ./gradlew build

      - name: Determine version
        id: determine_version
        run: |
          Write-Output "version_num=$(./gradlew -q printVersion)" >> $GITHUB_OUTPUT
          Write-Output "version=v$version_num" >> $GITHUB_OUTPUT
          Write-Output "$version"

      - name: Get previous version
        id: previous_version
        run: Write-Output "prev_version=$(git describe --tags $(git rev-list --tags --max-count=1))" >> $GITHUB_OUTPUT

      - name: Check if version has changed
        id: version_changed
        run: Write-Output "changed=${{ steps.determine_version.outputs.version != steps.previous_version.outputs.prev_version }}"  >> $GITHUB_OUTPUT

      - name: Generate release notes
        id: release_notes
        if: ${{ steps.version_changed.outputs.changed == 'true' }}
        run: |
          Write-Output "release_notes=$(git log $(git describe --tags $(git rev-list --tags --max-count=1))..HEAD --oneline)"  >> $GITHUB_OUTPUT

      - name: Build JAR file
        id: build_jar
        if: ${{ steps.version_changed.outputs.changed == 'true' }}
        run: ./gradlew build

      - name: Create release
        id: create_release
        if: ${{ steps.version_changed.outputs.changed == 'true' }}
        uses: softprops/action-gh-release@v1
        with:
          files: build/libs/ACSecurity-${{ steps.determine_version.outputs.version_num }}.jar
          tag_name: ${{ steps.determine_version.outputs.version }}
          name: ${{ steps.determine_version.outputs.version }}
          body: |
            ${ {steps.release_notes.outputs.release_notes} }

解决方案:实现守护进程复用

1. 固定Gradle用户目录,共享缓存与守护进程

GitHub Actions自托管Runner默认会为每个job创建临时工作目录,但Gradle守护进程的状态存储在用户主目录下的.gradle文件夹中。可以在工作流中显式指定统一的GRADLE_USER_HOME,确保所有job共享同一个缓存和守护进程池:

jobs:
  release:
    runs-on: self-hosted
    env:
      GRADLE_USER_HOME: C:\gradle-shared-cache # 固定路径,确保Runner有读写权限
      # 或者使用Runner工作区的固定子目录:${{ runner.workspace }}/.gradle

2. 保证JDK环境完全一致

actions/setup-java默认会将JDK下载到临时目录,每次job的JDK路径可能不同,导致Gradle认为守护进程不兼容。可以指定固定的JDK安装路径,或者让setup-java使用本地已安装的JDK:

- name: Set up JDK
  uses: actions/setup-java@v3.13.0
  with:
    distribution: 'adopt'
    java-version: '21'
    java-package: jdk
    architecture: x64
    cache: gradle # 启用Gradle缓存,同时稳定JDK环境

另外,确保Runner上的JDK版本固定,避免每次下载不同的构建包。

3. 延长守护进程空闲存活时间

在项目根目录的gradle.properties或全局的%USERPROFILE%\.gradle\gradle.properties中添加以下配置,让空闲守护进程存活更久:

org.gradle.daemon.idletimeout=3600000 # 空闲1小时后再停止,默认是10分钟
org.gradle.daemon.maxIdleTime=7200000 # 最大空闲存活2小时

4. 合并Gradle任务,减少启动次数

你的工作流中两次调用./gradlew build,可以合并成一次调用,避免多次启动守护进程。比如将构建、测试和版本号获取合并:

- name: Build, test and retrieve version
  id: build_version
  run: |
    ./gradlew build
    $version_num = ./gradlew -q printVersion
    Write-Output "version_num=$version_num" >> $GITHUB_OUTPUT
    Write-Output "version=v$version_num" >> $GITHUB_OUTPUT

这样只需要启动一次Gradle守护进程,完成多个任务。

为什么之前的守护进程会显示“不兼容”

Gradle守护进程的兼容性由多个核心因素决定,只要有一项不匹配就会被标记为无法复用:

  • JDK版本/路径:如果之前的守护进程是用不同版本的JDK,或者相同版本但安装路径不同(比如setup-java每次下载到临时目录),Gradle会判定不兼容。这是最常见的原因。
  • Gradle版本:项目的Gradle Wrapper版本变化,会导致守护进程无法复用。
  • 环境变量:JAVA_HOME、GRADLE_USER_HOME等关键环境变量变更,会让Gradle启动新的守护进程。
  • 项目配置:build.gradle或settings.gradle中的重大配置变更,也可能导致守护进程不兼容,但这种情况较少见。

你提到是同一项目的之前构建,大概率是JDK路径的变化导致的——每次setup-java都下载新的JDK到临时目录,使得JAVA_HOME不同,从而让Gradle认为之前的守护进程与当前环境不兼容。

内容的提问来源于stack exchange,提问作者ThrownRedstone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:06:06