第2章 Gradle守护进程与配置缓存

2.1 原理概述

Gradle守护进程(Daemon)是一个长期运行的JVM进程,用于缓存构建元数据、类加载器、插件状态和项目配置信息。启用守护进程后,每次构建不再重新初始化整个Gradle运行时,而是复用已存在的进程,从而大幅缩短构建启动时间。

配置缓存(Configuration Cache)是Gradle 6.6+引入的优化技术。它将配置阶段的计算结果(Gradle对象图、Task依赖关系、属性值等)序列化到磁盘缓存中。当项目文件和构建逻辑未改变时,后续构建可以跳过整个配置阶段,直接从缓存反序列化配置结果,使配置耗时从秒级降至毫秒级。

守护进程与配置缓存协同工作:守护进程提供JVM的内存和类加载缓存,配置缓存提供磁盘级的配置结果快照。两者结合能将Android多模块项目的增量构建提速40%~60%。

关键指标:守护进程使构建启动时间减少70%以上;配置缓存使配置阶段耗时从2~5秒降至0.1~0.3秒(视项目规模而定)。

2.2 守护进程持久化配置

守护进程默认启用(Gradle 3.0+)。你可以通过以下方式显式控制其行为。

配置位置参数说明
gradle.propertiesorg.gradle.daemon=true开启守护进程(默认值)
gradle.propertiesorg.gradle.daemon.idletimeout=600000守护进程空闲超时(毫秒),默认10分钟。超时后自动停止以释放内存。
gradle.propertiesorg.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m为守护进程分配堆内存和元空间,避免OOM
命令行--daemon / --no-daemon临时覆盖当前构建的守护进程策略

建议在~/.gradle/gradle.properties或项目根目录的gradle.properties中写入以下配置以实现守护进程持久化:

org.gradle.daemon=true
org.gradle.daemon.idletimeout=1800000   # 30分钟空闲超时
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1g
org.gradle.parallel=true

2.3 配置缓存开关配置

配置缓存通过Gradle属性或命令行启用。注意:配置缓存与某些插件(如自定义Transform、Kotlin MPP)存在兼容性问题,首次启用需仔细测试。

方式配置内容生效范围
Gradle属性org.gradle.configuration-cache=true全局/项目级
命令行--configuration-cache单次构建
禁用缓存gradle --no-configuration-cache build单次构建
清理缓存gradle --configuration-cache rebuild清空并重新缓存(调试用)

典型配置文件示例:

# gradle.properties(项目根目录)
org.gradle.configuration-cache=true
# 允许在配置缓存模式下使用Kotlin脚本(适配部分场景)
org.gradle.configuration-cache.internal.test-warning-log=true
# 最大缓存大小(默认200MB,大项目建议提升)
org.gradle.cache.size.max=1g

2.4 守护进程与配置缓存交互流程

理解核心流程:配置缓存只在守护进程中生效。首次构建仍须完整执行配置阶段,并将结果写入磁盘缓存;后续构建若项目文件未变,守护进程直接从缓存反序列化配置,跳过Task依赖解析和插件初始化。
守护进程与配置缓存生命周期 守护进程启动 首次完整配置 写出配置缓存 (磁盘缓存文件) 反序列化配置缓存 Task执行与缓存 构建输入变化检测 (项目文件/脚本) 配置缓存失效 → 回退完整配置

2.5 常见冲突与解决

启用配置缓存后可能遇到以下冲突,需针对性处理:

问题表现解决方案
守护进程内存不足 构建失败:OutOfMemoryError: Metaspace 增大JVM堆和元空间:-Xmx4g -XX:MaxMetaspaceSize=1g;同时减少空闲超时以释放资源。
配置缓存失效频繁 每次构建都重新配置,未命中缓存 检查buildSrc、自定义插件或Gradle版本是否修改;使用--configuration-cache rebuild强制清理重新缓存。
Transform API或Kotlin KSP不兼容 构建报错:Configuration cache does not support Transform 在gradle.properties中设置org.gradle.configuration-cache.internal.transform-compat=true(实验);或为相关模块关闭配置缓存。
多模块增量构建变慢 Task输入/输出声明不完整导致缓存降级 检查Task的@InputFiles、@OutputDirectory等注解是否准确;使用--scan生成构建扫描分析缓存命中率。
守护进程版本不一致 多个Gradle版本的项目共用守护进程导致崩溃 每个项目使用独立的Gradle wrapper;在gradle.properties中设置org.gradle.daemon.idletimeout=0(不共享)。
调试建议:在发生配置缓存相关错误时,先使用gradle --no-configuration-cache build确认是否为缓存问题。若构建正常,则逐步启用缓存并观察gradle/build/tmp/configuration-cache/report.html中的详细报告。

2.6 性能与稳定性优化

  • 守护进程内存控制:为每个守护进程分配固定堆大小,避免因系统内存不足而频繁GC。推荐值为-Xmx4g -XX:MaxMetaspaceSize=1g(根据项目模块数调整)。
  • 配置缓存预热:CI场景下首次构建后保留缓存目录(.gradle/configuration-cache),避免每次CI都重复配置。
  • 构建并行度:配合org.gradle.parallel=true,配置缓存与并行Task同时生效,最大化CPU利用率。
  • 分级清理策略:定期清理过大的守护进程缓存和配置缓存,防止磁盘占用膨胀。使用gradle --stop停止所有守护进程,手动删除~/.gradle/caches下的历史缓存。

2.7 验证与部署

在本地开发环境验证守护进程和配置缓存是否生效:

# 查看守护进程状态
gradle --status

# 第一次构建(记录耗时)
gradle clean assembleDebug --no-configuration-cache

# 第二次构建(启用配置缓存,观测配置阶段耗时)
gradle assembleDebug --configuration-cache

# 输出对比:配置阶段时间应明显缩短

在CI环境中推荐显式启用:

# 在CI的gradle.properties中
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.configuration-cache=true
org.gradle.caching=true
org.gradle.vfs.watch=true   # 文件系统观察者(提高文件变化检测速度)

注意:部分CI平台(如Jenkins)默认禁用守护进程,需在启动命令后追加--daemon。同时确保CI工作目录的~/.gradle具有持久化存储,否则每次构建都会重建守护进程和配置缓存。