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 s2.1 s2.3 GB
maxSizeInBytes=500MB45 s2.1 s≤ 500 MB
maxAgeInDays=145 s2.1 s≤ 80 MB(每日自动清理)

当设置合理大小限制后,缓存命中率与无限模式完全相同(因为 LRU 仅淘汰最久未使用的条目,不影响当前依赖),但磁盘占用可控,避免 CI 环境磁盘爆满。

3.5 调试步骤:分析缓存未命中原因

若本地缓存始终未命中,请按以下步骤排查:

  1. 检查日志级别:使用 --debug 输出完整缓存决策。
  2. 确认缓存键差异:对比前后构建的 task 输入哈希值(使用 --scan 构建扫描)。
  3. 验证缓存目录权限:确保运行 Gradle 的用户对 directory 有读写权限。
  4. 检查是否被禁用:isEnabled = false 或全局 --no-build-cache 会完全绕过缓存。
  5. 检查大小限制是否过小:若 maxSizeInBytes 小于单次构建产生的缓存数据量,则缓存始终无法完整保留。
常见错误: 在 Kotlin DSL 中,directory 必须使用 File(rootProject.rootDir, "..."),不能使用字符串。错误写法 directory = ".gradle-build-cache" 会导致 Gradle 抛出 Type mismatch 异常。

3.6 本地缓存配置流程结构

本地缓存配置流程与数据流 buildCache 配置块 local { … } directory 目录位置 maxSizeInBytes 大小限制 maxAgeInDays 过期天数 本地文件系统缓存(.gradle-build-cache/) 键值对存储|LRU 淘汰|过期清理 Gradle 构建任务 ⚠️ 三个参数至少配置一个

上图展示了 buildCache → local → 三个核心参数 → 本地文件系统 → 构建任务 的配置链路。务必同时指定 maxSizeInBytes 与 maxAgeInDays,避免磁盘膨胀或缓存失效过快。

3.7 常见错误与修复动作

错误现象根因修复动作
构建日志显示 Local build cache is disabledisEnabled = false 显式禁用删除 isEnabled = false 或将值改为 true
缓存目录持续增长,超出限制maxSizeInBytes 未设置或值太大设置合理的 maxSizeInBytes(如 512 MB)
缓存文件权限不足(Linux CI)容器内运行 Gradle 的用户不一致使用固定 UID 挂载缓存目录,或 chown 给正确用户
Kotlin DSL 编译错误 Type mismatch: inferred type is String but File was expecteddirectory 直接赋字符串改为 directory = File(rootProject.rootDir, "my-cache")

警告: 切勿在多构建共享的缓存目录中同时运行不同 JDK 或 Gradle 版本的构建,这会导致缓存键冲突,引发 缓存投毒(Cache Poisoning)——错误地复用旧版本的编译输出,产生难以调试的运行时异常。