3. 本地缓存配置实战:buildCache 配置块、local 类型、目录位置、存储大小限制
本章深入 本地缓存配置,这是 Gradle 构建缓存中最基础、最常用的回退与加速手段。你将学习通过 buildCache 配置块声明 local 类型,并精确控制缓存目录位置与存储大小限制,避免磁盘膨胀或缓存失效过快。
3.1 核心概念:buildCache 与 local 类型
buildCache 是 Gradle 7+ 中专用的缓存顶层配置块,用于声明后端来源。其中 local 类型表示本地文件系统缓存,是默认启用的后端。每次构建时,Gradle 会将可缓存的输出(如 Jar 文件、类文件、测试报告等)以键值对形式存入本地目录,并在后续构建中按需检索。
| 配置块 | 类型 | 默认目录 | 作用 |
|---|---|---|---|
buildCache | 顶级配置块 | — | 声明所有缓存后端(本地 + 远程) |
local | 缓存后端 | ~/.gradle/caches/build-cache-1 | 本地文件系统缓存,速度最快 |
3.2 配置本地缓存目录位置与存储限制
通过 directory 属性可自定义缓存路径,通过 maxSizeInBytes 和 maxAgeInDays 控制存储上限与过期时间。以下示例均使用 Kotlin DSL:
// build.gradle.kts
buildCache {
local {
// 自定义目录(推荐使用项目同级目录,便于清理)
directory = File(rootProject.rootDir, ".gradle-build-cache")
// 最大缓存大小(字节),超出后按 LRU 清理旧条目
maxSizeInBytes = 512 * 1024 * 1024L // 512 MB
// 条目最大存活天数,超过则视为过期(即使未达大小上限也会被清理)
maxAgeInDays = 7
// 始终启用本地缓存
isEnabled = true
}
}
~/.gradle/caches/build-cache-1 不会自动清理,若不设 maxSizeInBytes,磁盘占用可能无限制增长。生产环境务必指定大小限制。
3.3 验证配置与查看当前缓存状态
配置生效后,可通过 Gradle 的 --info 日志观察缓存目录路径与命中行为:
# 构建一次(生成缓存)
./gradlew assemble --info | grep -i "build cache"
# 输出示例:
# Using local build cache at /home/user/project/.gradle-build-cache
# Stored build cache entry at key 1a2b3c...
# Retrieved build cache entry for task :compileJava
使用以下命令快速查看缓存目录大小与条目数:
# 查看缓存目录占用
du -sh .gradle-build-cache
# 统计缓存条目(每个子目录代表一个缓存键)
ls -la .gradle-build-cache/ | wc -l
3.4 性能对比:无限增长 vs 有限缓存
以下数据基于同一项目(10 个模块,约 5 万行 Java + Kotlin)进行全量构建对比:
| 配置策略 | 总构建时间(首次) | 第二次构建(无代码变更) | 磁盘占用(持续 30 次构建) |
|---|---|---|---|
| 无限制(默认) | 45 s | 2.1 s | 2.3 GB |
maxSizeInBytes=500MB | 45 s | 2.1 s | ≤ 500 MB |
maxAgeInDays=1 | 45 s | 2.1 s | ≤ 80 MB(每日自动清理) |
当设置合理大小限制后,缓存命中率与无限模式完全相同(因为 LRU 仅淘汰最久未使用的条目,不影响当前依赖),但磁盘占用可控,避免 CI 环境磁盘爆满。
3.5 调试步骤:分析缓存未命中原因
若本地缓存始终未命中,请按以下步骤排查:
- 检查日志级别:使用
--debug输出完整缓存决策。 - 确认缓存键差异:对比前后构建的 task 输入哈希值(使用
--scan构建扫描)。 - 验证缓存目录权限:确保运行 Gradle 的用户对
directory有读写权限。 - 检查是否被禁用:
isEnabled = false或全局--no-build-cache会完全绕过缓存。 - 检查大小限制是否过小:若
maxSizeInBytes小于单次构建产生的缓存数据量,则缓存始终无法完整保留。
directory 必须使用 File(rootProject.rootDir, "..."),不能使用字符串。错误写法 directory = ".gradle-build-cache" 会导致 Gradle 抛出 Type mismatch 异常。
3.6 本地缓存配置流程结构
上图展示了 buildCache → local → 三个核心参数 → 本地文件系统 → 构建任务 的配置链路。务必同时指定 maxSizeInBytes 与 maxAgeInDays,避免磁盘膨胀或缓存失效过快。
3.7 常见错误与修复动作
| 错误现象 | 根因 | 修复动作 |
|---|---|---|
构建日志显示 Local build cache is disabled | isEnabled = false 显式禁用 | 删除 isEnabled = false 或将值改为 true |
| 缓存目录持续增长,超出限制 | maxSizeInBytes 未设置或值太大 | 设置合理的 maxSizeInBytes(如 512 MB) |
| 缓存文件权限不足(Linux CI) | 容器内运行 Gradle 的用户不一致 | 使用固定 UID 挂载缓存目录,或 chown 给正确用户 |
Kotlin DSL 编译错误 Type mismatch: inferred type is String but File was expected | directory 直接赋字符串 | 改为 directory = File(rootProject.rootDir, "my-cache") |
警告: 切勿在多构建共享的缓存目录中同时运行不同 JDK 或 Gradle 版本的构建,这会导致缓存键冲突,引发 缓存投毒(Cache Poisoning)——错误地复用旧版本的编译输出,产生难以调试的运行时异常。