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 块完成,也可通过系统属性或环境变量覆盖。下面是标准化配置步骤:
- 指定缓存目录 – 使用
directory方法指向一个或相对路径(相对于项目根目录)。 - 设置缓存大小限制 – 通过
maxCacheSizeInBytes限制缓存占用的最大磁盘空间。 - 配置清理策略 – 利用
removeUnusedEntriesAfterDays自动清除超过指定天数未被访问的条目。 - 启用多项目共享 – 多个项目共享同一个本地缓存目录,避免重复缓存。
- 验证与调试 – 通过构建扫描或缓存信息任务检查缓存状态。
提示:如果在 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 中的 buildCache.local { } 块。通过调整 directory、maxCacheSizeInBytes、removeUnusedEntriesAfterDays 和 isReadOnly,你可以灵活控制缓存位置、容量、清理策略以及多项目共享方式。每次调整后建议执行 gradle buildCacheInfo 验证配置是否生效。