3. 本地缓存配置:目录、大小限制、清理策略与多项目共享

本地缓存是 Gradle 构建缓存的基础数据层。每一次构建产生的缓存条目都存储在本地文件系统中,后续执行相同输入的任务时直接复用。合理配置本地缓存的目录位置、容量上限、自动清理规则以及多项目共享方式,能显著提升开发与 CI 环境下的构建效率,避免磁盘膨胀和权限冲突。

3.1 原理概述

Gradle 本地缓存在磁盘上按哈希目录分层存储,每个缓存条目标识通过输入属性的规范哈希值计算得出。默认路径在用户目录 ~/.gradle/caches/build-cache-1 下,目录结构如下:

~/.gradle/caches/build-cache-1/
├── ab/
├── cd/
└── ef/
    └── 19ab... (哈希命名的目录)
        ├── output.bin
        └── output.properties

每个缓存条目包含输出文件(output.bin)和元数据(output.properties)。当 Gradle 执行任务时,先检查本地缓存中是否有与当前输入哈希匹配的条目,若命中则跳过任务执行,直接解压输出。

3.2 配置实现流程

本地缓存的配置主要通过 settings.gradle(.kts)中的 buildCache 块完成,也可通过系统属性或环境变量覆盖。下面是标准化配置步骤:

  1. 指定缓存目录 – 使用 directory 方法指向一个或相对路径(相对于项目根目录)。
  2. 设置缓存大小限制 – 通过 maxCacheSizeInBytes 限制缓存占用的最大磁盘空间。
  3. 配置清理策略 – 利用 removeUnusedEntriesAfterDays 自动清除超过指定天数未被访问的条目。
  4. 启用多项目共享 – 多个项目共享同一个本地缓存目录,避免重复缓存。
  5. 验证与调试 – 通过构建扫描或缓存信息任务检查缓存状态。
提示:如果在 CI 环境下使用共享缓存,建议将目录设置为挂载的持久化卷(如 /opt/cache/gradle),并确保所有构建进程有读写权限。

3.3 配置详解与代码示例

以下完整的 settings.gradle.kts 配置展示了最常用的本地缓存参数:

// settings.gradle.kts
buildCache {
    local {
        // 1. 自定义缓存目录(相对路径:项目根目录下的 .my-build-cache)
        directory = File(rootDir, ".my-build-cache")
        
        // 2. 缓存最大字节数:1 GB
        maxCacheSizeInBytes = 1L * 1024 * 1024 * 1024
        
        // 3. 自动清理:超过 14 天未使用的条目将被删除
        removeUnusedEntriesAfterDays = 14
        
        // 4. 是否启用(默认 true)
        enabled = true
        
        // 5. 是否只读(多项目共享时可以在某些节点设为只读)
        isReadOnly = false
    }
}

在 gradle.properties 中也可以通过系统属性临时覆盖(优先级较低):

# gradle.properties
org.gradle.caching.local.enabled=true
# 下面两个属性仅用于示例,实际建议在 settings 中控制
# org.gradle.caching.local.directory=/tmp/gradle-cache
# org.gradle.caching.local.max-cache-size=500m

3.4 清理策略对比

策略 配置方式 触发时机 适用场景
基于 TTL(存活天数) removeUnusedEntriesAfterDays = N 每次构建前/后台线程扫描 开发环境,避免缓存无限增长
基于大小限制 maxCacheSizeInBytes = X 缓存写入时触发淘汰 CI 环境,磁盘空间有限
手动清理 执行 gradle cleanBuildCache 用户显式触发 缓存损坏或需要完全重置

3.5 多项目本地缓存共享

当多个 Gradle 项目在同一台机器上构建时,如果它们使用了相同的依赖与任务输入,共享本地缓存可以大幅减少重复构建。核心做法是将所有项目的缓存目录指向同一个位置:

// 在 A 项目和 B 项目的 settings.gradle.kts 中分别配置
buildCache {
    local {
        directory = File("/shared/gradle-build-cache")
        isReadOnly = false   // 仅第一个项目可写,其他项目设为只读避免并发写入冲突
    }
}

若项目数量较多且存在并发写入的风险,推荐采用“一写多读”模式:

  • 主 CI 节点或开发者设定 isReadOnly = false(可写)。
  • 其他节点设定 isReadOnly = true(只读),避免多个进程同时写入导致缓存损坏。
  • 通过 --max-workers 1 进一步降低并发写入的可能性。
注意: Windows 系统下共享缓存目录需注意文件路径长度限制(MAX_PATH 260 字符)。建议缓存目录路径尽量简短,或开启长路径支持。

3.6 调试与验证

构建完成后,可以通过以下命令查看缓存命中情况:

# 打印本次构建的缓存统计信息
gradle build --build-cache -Dorg.gradle.caching.debug=true

# 查看缓存存储的详细信息(条目数、总大小)
gradle buildCacheInfo

若怀疑缓存未生效,检查构建日志中的 FROM-CACHE 标记:

Task :compileJava (from cache)   // 表示从本地缓存命中
Task :compileJava (not from cache) // 未命中,需重新执行

3.7 常见错误与解决方案

  • 错误:Permission denied(权限不足) – 缓存目录的父目录不可写。解决方案:使用 chmod 或修改 directory 为当前用户可写的路径。
  • 错误:No space left on device – 磁盘已满。解决方案:降低 maxCacheSizeInBytes 或执行 cleanBuildCache。
  • 错误:Cache corruption after concurrent write – 多个 Gradle 进程同时写入同一缓存条目。解决方案:除一个节点外,其余设为只读;或使用远程缓存。
  • 错误:Entry too large (超过 2GB) – Gradle 本地缓存不支持单个输出>2GB。解决方案:考虑将超大输出排除在缓存外(outputs.cacheIf { false })。

3.8 性能优化建议

优化点 推荐做法 效果
存储介质 将缓存目录放在 SSD 显著缩短解压/读取时间
缓存大小 根据磁盘空间设置合理上限(如 2~5 GB) 避免频繁淘汰导致热点丢失
并发写入 多项目共享时仅允许一个写入节点 避免缓存损坏
清理频率 removeUnusedEntriesAfterDays = 7~30 平衡空间与命中率
压缩 Gradle 7 后默认使用 ZSTD 压缩(自动) 减少存储空间,略微增加 CPU

3.9 本地缓存配置原理图

本地缓存配置架构 本地缓存配置流程与结构 settings.gradle.kts 配置 缓存目录 (directory) 大小限制 (maxCacheSizeInBytes) 清理策略 (removeUnused…) 读写模式 (isReadOnly) 磁盘上的缓存结构(示例) /shared/gradle-cache/ ├── ab/ ├── cd/ └── ... 哈希目录 → output.bin + output.properties 多项目共享要点 • 所有项目 directory 指向同一路径 • 仅一个项目设为可写,其余只读
要点总结:本地缓存配置的核心是 settings.gradle 中的 buildCache.local { } 块。通过调整 directory、maxCacheSizeInBytes、removeUnusedEntriesAfterDays 和 isReadOnly,你可以灵活控制缓存位置、容量、清理策略以及多项目共享方式。每次调整后建议执行 gradle buildCacheInfo 验证配置是否生效。