1.1 缓存失效现象识别
Gradle 构建缓存(Build Cache)是加速增量构建的核心机制,但其失效场景往往隐蔽且容易被误判。当缓存失效时,可能表现为构建输出异常、增量构建不生效或依赖解析失败。更危险的是,构建看似成功,却输出了过期或错误的内容——这类“无症状失效”是排查难度最高的故障。
本章将引导你通过现象分类 → 现场数据采集 → 根因定位 → 修复与验证 → 防复发的闭环流程,系统性地识别并处置缓存失效问题。
⚠ 常见误报信号警示
并非所有“构建变慢”或“输出变化”都由缓存失效引起。开发环境差异、增量编译未启用、并行任务冲突等都可能产生相似表象。本节末尾将提供一份误报信号校验清单,帮助你在投入深入排查前快速过滤干扰项。
并非所有“构建变慢”或“输出变化”都由缓存失效引起。开发环境差异、增量编译未启用、并行任务冲突等都可能产生相似表象。本节末尾将提供一份误报信号校验清单,帮助你在投入深入排查前快速过滤干扰项。
1.1.1 四种表象速判表
以下表格帮助你快速根据现场现象定位缓存失效类别,并预判后续采集动作。
| 表象 | 典型观察点 | 最可能故障域 | 第一现场采集命令 |
|---|---|---|---|
| 构建输出异常 | JAR/AAR 内容与源码不一致 | 输出产物缓存被污染或过期 | |
| 增量构建不生效 | 每次都是全量编译,但未改动代码 | 增量编译缓存元数据失效 | |
| 依赖解析失败 | 报错 "Could not resolve ..." 或 "checksum failed" | 依赖缓存损坏或格式异常 | |
| 误报信号 | 构建变慢但无错误,且每次结果 diff 一致 | 非缓存问题,环境因素 | |
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 但产物未更新。
💡 增量构建故障树(根因预判)
- 检查 task 输入文件快照是否由于时间戳漂移而失效(跨不同文件系统)。
- 检查
build/目录是否被外部工具(如 IDE 自动清理)误删。 - 检查是否有非确定性任务(如动态生成的文件名):
./gradlew :app:compileDebugJavaWithJavac --info | grep "non-incremental"
③ 依赖解析失败
表现:构建日志抛 Could not resolve dependency、checksum mismatch、POM parsing error。有时仅某个 CI 环境复现。
| 观察日志片段 | 排查表 - 根因 | 数据采集命令 |
|---|---|---|
Received status code 403 |
远程仓库凭证过期或缓存了未授权响应 | |
SHA1 digest mismatch |
本地缓存 POM/AAR 文件被破坏 | |
Could not find ... (cached) |
缓存解析结果中记录了“不存在”,导致后续不再重试 | |
④ 常见误报信号
以下情况不是缓存失效,但容易被误认为缓存问题。请先检查这些因素,避免走冤枉路:
- 机器资源不足: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 版本间的缓存格式不兼容。