1.1 缓存失效现象识别

Gradle 构建缓存(Build Cache)是加速增量构建的核心机制,但其失效场景往往隐蔽且容易被误判。当缓存失效时,可能表现为构建输出异常、增量构建不生效或依赖解析失败。更危险的是,构建看似成功,却输出了过期或错误的内容——这类“无症状失效”是排查难度最高的故障。

本章将引导你通过现象分类 → 现场数据采集 → 根因定位 → 修复与验证 → 防复发的闭环流程,系统性地识别并处置缓存失效问题。

⚠ 常见误报信号警示
并非所有“构建变慢”或“输出变化”都由缓存失效引起。开发环境差异、增量编译未启用、并行任务冲突等都可能产生相似表象。本节末尾将提供一份误报信号校验清单,帮助你在投入深入排查前快速过滤干扰项。
构建缓存失效现象识别框架 Gradle 构建缓存 构建输出异常 增量构建不生效 依赖解析失败 内容缺失 版本不正确 产物损坏 完全重建(所有模块) 任务跳步但结果未更新 解析超时 POM 校验失败 ⚠ 常见误报信号(干扰项) 机器内存不足 增量编译未启用 并行任务冲突

1.1.1 四种表象速判表

以下表格帮助你快速根据现场现象定位缓存失效类别,并预判后续采集动作。

表象 典型观察点 最可能故障域 第一现场采集命令
构建输出异常 JAR/AAR 内容与源码不一致 输出产物缓存被污染或过期
./gradlew clean build --info | grep "cache"
增量构建不生效 每次都是全量编译,但未改动代码 增量编译缓存元数据失效
./gradlew assembleDebug --scan
依赖解析失败 报错 "Could not resolve ..." 或 "checksum failed" 依赖缓存损坏或格式异常
ls ~/.gradle/caches/modules-2/
误报信号 构建变慢但无错误,且每次结果 diff 一致 非缓存问题,环境因素
./gradlew --version && free -m

1.1.2 现象详解与识别规则

① 构建输出异常

表现:构建产物(如 APK、JAR)体积异常、版本号与代码不匹配、资源缺失,或运行时出现 ClassNotFoundException 但代码中类名存在。

判断规则:
  • 对比两次不含缓存的构建输出:diff <(unzip -l build/libs/foo.jar) <(unzip -l build_no_cache/foo.jar)
  • 检查构建缓存 key 是否包含不必要的环境变量:grep "org.gradle.caching" gradle.properties
  • 开启 --rerun-tasks 后问题是否消失 → 确认是缓存引起。

② 增量构建不生效

表现:未修改任何源代码或资源,但每次执行 build 都会重新编译所有 Java/Kotlin 文件,或所有 task 都显示 UP-TO-DATE 但产物未更新。

💡 增量构建故障树(根因预判)
  1. 检查 task 输入文件快照是否由于时间戳漂移而失效(跨不同文件系统)。
  2. 检查 build/ 目录是否被外部工具(如 IDE 自动清理)误删。
  3. 检查是否有非确定性任务(如动态生成的文件名):./gradlew :app:compileDebugJavaWithJavac --info | grep "non-incremental"

③ 依赖解析失败

表现:构建日志抛 Could not resolve dependency、checksum mismatch、POM parsing error。有时仅某个 CI 环境复现。

观察日志片段 排查表 - 根因 数据采集命令
Received status code 403 远程仓库凭证过期或缓存了未授权响应
curl -I https://your.repo/maven/
SHA1 digest mismatch 本地缓存 POM/AAR 文件被破坏
rm -rf ~/.gradle/caches/modules-2/files-2.1/
Could not find ... (cached) 缓存解析结果中记录了“不存在”,导致后续不再重试
ls ~/.gradle/caches/modules-2/metadata-2.0/

④ 常见误报信号

以下情况不是缓存失效,但容易被误认为缓存问题。请先检查这些因素,避免走冤枉路:

  • 机器资源不足:CPU 满载、内存不足 I/O 升高 → 构建慢,非缓存问题。
  • 增量编译开关未开启:部分 module 未设置 kotlin.incremental=true。
  • 并行 task 冲突:自定义 task 的输出目录与缓存 task 的输出目录重叠。
  • 本地 .gradle/ 目录权限异常:read-only filesystem 导致无法写入缓存索引。
🔍 现场快照建议
遇到疑似缓存故障时,在清理缓存前先执行:
# 保存失效前快照
mkdir -p /tmp/cache_snapshot_$(date +%Y%m%d_%H%M%S)
cp -r ~/.gradle/caches/build-cache-1 /tmp/cache_snapshot_$(date +%Y%m%d_%H%M%S)/build-cache-1
./gradlew --stop
# 记录构建扫描ID
./gradlew assembleDebug --scan > build_scan_link.txt

1.1.3 现象识别的“预防”基线

建立团队级缓存健康检查,将以下检查项纳入 CI 流水线或每日巡检:

  • 每次提交前:执行 ./gradlew clean build --build-cache 并比较产物与基线。
  • 每周一轮:检查缓存命中率阈值(--scan 报告中 Cache Hit Rate 应 > 70%)。
  • 每次大版本升级:清空缓存一次并重新预热,规避 Gradle 版本间的缓存格式不兼容。