gradle 增量构建的本质是通过精确声明任务的输入(inputs)和输出(outputs)实现“只重做有变化的事”,输入未变则跳过任务并复用输出;需正确标注@input、@inputfiles、@outputdirectory等注解,避免非确定性输入和干扰配置,并配合构建缓存与并行执行以最大化效能。

Gradle 的增量构建机制本质是“只重做有变化的事”。它不靠猜,而是通过精确追踪每个任务的输入(inputs)和输出(outputs),在二次执行时比对输入是否变更——没变就跳过任务,直接复用上次的输出。只要配置得当,修改一行 Java 代码后,编译可能仅耗时几百毫秒,而非几分钟。
明确声明任务的 inputs 和 outputs
Gradle 默认对标准插件(如 JavaCompile、KotlinCompile)已内置增量支持,但前提是项目未破坏其默认约定。需确保:
- 源码路径按惯例放在 src/main/java 等标准目录,不要用
sourceSets.main.java.srcDirs = [...]随意覆盖为动态路径 - 避免在编译任务中混入非确定性输入,例如:
System.currentTimeMillis()、随机数、未加@Internal注解的调试开关字段 - 自定义任务必须显式标注:
@Input(简单值)、@InputFiles(输入文件集合)、@OutputDirectory(输出目录),且 getter 方法不可为private
关闭干扰增量判定的配置
某些看似无害的设置会隐式让 Gradle 认为“输入总在变”,从而禁用增量:
- 禁用
compileJava.options.fork = true(开启 fork 会使 Gradle 难以捕获完整 classpath 变化) - 移除
compileJava.options.compilerArgs += ['-Xlint:all']类动态参数(除非加@Internal注解) - 不要在
build.gradle中用fileTree或new File(...)构造输入路径——改用layout.projectDirectory.file(...)等惰性 API
配合构建缓存与并行执行
增量构建是基础,叠加缓存与并行才能释放最大效能:
- 在 gradle.properties 中启用:
org.gradle.caching=true(本地缓存)和org.gradle.parallel=true(跨模块并行) - CI 环境建议加远程缓存:
org.gradle.configuration-cache=true(配置缓存,Gradle 8.4+)可进一步缩短配置阶段耗时 - 验证是否生效:运行
./gradlew compileJava --info,看到Skipping task ':app:compileJava' as it is up-to-date即表示增量命中
排查常见失效场景
如果修改代码后仍全量编译,优先检查以下几点:
-
clean 操作被误触发:CI 脚本或 IDE 插件自动执行了
clean,清空输出导致增量失效 -
资源文件未声明为输入:比如自定义代码生成任务读取
src/main/resources/config.json,但未用@InputFile标注该文件 -
IDE 同步问题:IntelliJ 的 “Build project automatically” 与 Gradle 增量逻辑不完全一致,建议关闭 IDE 自动构建,统一用
./gradlew compileJava - 依赖 SNAPSHOT 版本频繁更新:强制 Gradle 检查远端变更,使依赖图不稳定,影响增量判断
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











