最近被AI生成的代码折磨得不轻——不是代码写得不对,是构建实在太慢了。我手头一个中型项目,组里所有人都用AI Agent辅助写代码,一个月下来代码量涨了40%,Gradle构建时间从2分钟一路膨胀到8分钟,CI上排队加跑完动不动就半小时。这个背景下,我把构建链整体升级了一遍:Gradle 9.4 + Java 26,配合配置缓存、构建缓存、依赖锁和镜像加速,把冷启动到出包的时间压到了40秒左右,验证一轮AI生成代码的反馈循环快了差不多10倍。这篇文章不聊AI写代码的用法,专门聊聊构建优化这条容易被忽略的链路,适合那些正在被Gradle构建速度拖后腿、或者在CI/CD里反复调试AI生成代码的团队参考。
1. AI生成代码涌入项目后,构建系统成了第一道瓶颈
1.1 AI生成的代码有哪些“反构建”特征
先说结论:AI生成代码对构建系统的杀伤力,比手写代码大得多。我排查了组里构建变慢的原因,发现不是单一因素,而是AI生成代码的一系列“反构建”特征叠在一起。
依赖声明过度是最典型的问题。AI写功能时倾向于“宁可多用不可漏用”,为了一个字符串工具方法,就能把整个Apache Commons或Guava拉进来。这在代码层面问题不大,但在Gradle里意味着每次依赖解析都要多处理几个仓库索引,任务图上也会多出几个不必要的jar包下载。最夸张的一次,AI生成的代码里import了三个不同的JSON库,而实际用到的只有一个。构建脚本里多出几十个直接依赖,整个依赖树膨胀得厉害,解析时间自然上去了。
文件数量和包结构膨胀同样致命。AI在生成新功能时,通常会新建一个包,放进十几个类,而不是去修改已有的类。跑一次增量构建,Gradle需要扫描的文件数量多了,编译出错的概率高了,增量编译的效果也变差了。更麻烦的是,AI生成的代码经常出现重复定义——同名的类、同名的资源文件、重复的常量定义,这些在编译期不一定报错,但会让编译器的符号解析慢很多。
还有一个隐蔽的问题:循环依赖。AI生成代码时很少考虑模块边界,经常出现A模块引用B模块、B模块又反向引用A模块的情况。手写代码时,开发者会下意识避免这种环形依赖;AI不懂这些,生成出来的模块依赖关系经常是一团乱麻。Gradle在配置阶段构建任务图时,遇到循环依赖只能一遍遍重试,这个时间损耗在构建日志里很隐蔽,但累积起来非常可观。
1.2 为什么Gradle是这场性能战里的主要战场
Java生态的构建工具里,Gradle虽然灵活,但它对构建脚本的执行模型决定了它对“脏代码”更敏感。Maven是约定优于配置,你往项目里扔多少代码,它的生命周期基本固定。Gradle不一样,它的构建脚本本质上是Groovy或Kotlin代码,每次构建都要先执行配置阶段,把整个任务图算出来,再进入执行阶段。
AI生成代码对这个模型是双重打击。一方面,AI会直接改写构建脚本——组里有人让AI帮忙加依赖,AI把整个build.gradle.kts重写了一遍,结果插件版本全部漂移,配置阶段疯狂报错,构建时间增加了好几倍。另一方面,AI生成的大量Java代码会显著增加编译任务的负载,特别是那些泛型推断极其复杂、Lambda嵌套很深的代码,javac在类型推断上花的时间远超平均水平。
打个比方:Gradle就像航班调度中心,原本一个小时调度100个航班,现在AI一口气加了300个航班,而且这些航班之间还互相冲突。调度中心本身设计得再好,也扛不住这种无序增量。所以AI时代的构建优化,核心不是去改Gradle的调度算法,而是让进入构建系统的代码更“规整”,同时把Gradle已有的优化机制全部打开,让每一次构建都尽量复用之前的结果。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Gradle 9.4 + Java 26:版本升级到底带来了什么
2.1 先分清三个“Java”:运行构建的JVM、编译目标的JVM、Daemon的JVM
升级之前,得先把一个容易混淆的概念理清楚:项目里的Java,实际有三个不同的角色。
- 运行Gradle本身的JVM:也就是执行gradlew脚本时,用来启动Gradle进程的那个Java。Gradle 9.x要求这个JVM至少是Java 17。
- 项目编译目标的JVM:你的代码编译成哪个版本的字节码,比如
sourceCompatibility、targetCompatibility或者toolchain里指定的版本。 - Gradle Daemon的JVM:Gradle启动后常驻后台的守护进程,它运行时的内存和GC行为直接影响构建性能。
很多报错,包括热搜里那个“the project's gradle version 6.7.1 is incompatible with the gradle jvm version”,本质就是这三个角色没有匹配好。Gradle 6.7.1这个版本根本不认识新版JDK的class文件格式,你非要用Java 26去运行它,它当然会报不兼容。这不是Gradle的问题,也不是Java的问题,是组合方式的问题。
我把项目升级到Gradle 9.4 + Java 26之后,建议所有团队优先用toolchain来管理编译目标,而不是手动设置sourceCompatibility和targetCompatibility。通过toolchain,Gradle会自动检测本地安装的JDK,找不到对应
