构建慢这件事,绝大多数团队都搞错了优化方向。
我见过太多项目组一抱怨 Gradle 慢,Leader 第一反应就是换 Mac、加内存、上固态,结果一万多块花出去,构建时间纹丝不动。然后一群人围着 Android Studio 里那个进度条大眼瞪小眼,谁也不知道瓶颈到底卡在哪个阶段。
先把结论放这儿:Gradle 构建慢,90% 的情况不是硬件问题,而是你没有把 Java 运行时、Gradle 配置策略和 Android 任务链这三层的关系理顺。这三层就像一辆车的发动机、变速箱和轮胎,任何一个环节不匹配,踩油门都白搭。
这篇文章我会把我压榨 Gradle 构建性能的完整思路拆开讲,从 JVM 底层参数到 Android 物理打包链路,每一步都给出可复现的配置和验证方法。适合被构建速度折磨了几个月、试过网上零散技巧但始终没系统解决的人,也适合想把自己项目的构建配置从“能用”提升到“能打”的 Android 开发者。
1. 构建慢不是因为电脑差:先把瓶颈量化出来
我接手过的每个“慢项目”,几乎都有一个共同特征:没人跑过构建分析。都是在凭感觉猜——有人说依赖太多,有人说资源文件太大,有人说该换电脑了。
其实 Gradle 自带一套相当完整的性能分析工具,只是大多数人装完 Android Studio 就再也没碰过这些命令。我强烈建议你做优化的第一步不是改任何配置,而是先量化。
1.1 用 --profile 和 --scan 给构建做一次全身体检
先跑一条最基础的命令,给当前项目生成一份构建画像:
bash复制./gradlew assembleDebug --profile --rerun-tasks
--profile 会在 build/reports/profile/ 目录下生成一份 HTML 报告,里面按阶段把构建时间拆得明明白白:初始化阶段、配置阶段、任务执行阶段,每个任务单独花了多少毫秒,一目了然。
--rerun-tasks 是我故意加的,因为如果不加,增量构建会让很多任务直接 UP-TO-DATE 跳过,你看到的只是缓存命中的假象,根本测不出真实耗时。
如果项目配置了 Build Scan(Gradle 7.x 以上用 --scan 参数),还能得到一份在线报告,包含依赖解析耗时、缓存命中率、GC 时间等更细粒度的数据。
这份报告拿到手,先看三个关键指标:
- 配置阶段耗时占比:如果配置阶段占了总时间 30% 以上,说明项目里大量任务在配置阶段被初始化了,这是后面第三个章节要解决的核心问题。
- 单任务耗时 Top 榜:排在前面的往往是
processDebugResources、dexBuilderDebug、mergeExtDexDebug之类的 Android 任务,或者是某些自定义的 Transform 任务。 - GC 时间:如果 GC 时间占了执行阶段的 15% 以上,说明 JVM 堆内存或垃圾回收器选型有问题。
1.2 一个小项目拖成“大慢车”的真实案例
有一个外包项目,业务代码不到 2 万行,但冷构建要跑 4 分 20 秒。当时团队给我的解释是“资源文件太大了”,我跑了一次 --profile 发现,光配置阶段就花了 47 秒。
点进去看详情,才发现在 build.gradle 的顶层直接执行了 new File(...).eachFile { ... } 去做资源目录扫描,还有一个自定义插件在配置阶段联网请求了一个接口来判断版本号。这两个操作本身就够慢的,而且每次构建都会执行,不管你改没改代码。
这就是典型的配置阶段污染——把本应在执行阶段做的事放到了配置阶段去做,导致每次构建的固定开销被无限放大。
在动任何 Gradle 配置之前,先找到真实的瓶颈在哪,这一步花 10 分钟,后面能省 10 个小时。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Java 运行时压榨:守护进程、内存与编译策略的正确姿势
第一层要优化的是 Gradle 所依赖的 Java 运行时。这一层最容易被忽视,因为 Android 开发者平时写代码不直接接触 JVM 参数,但这些参数恰恰决定了构建的“底力”。
2.1 守护进程不是越大越好:org.gradle.jvmargs 的正确打开方式
网上流传的配置经常是抄来抄去,什么 -Xmx8g、-Xmx16g 都有人敢填。但 JVM 堆内存不是越大越好——堆太大导致 GC 停顿时间变长,堆太小导致频繁 Full GC,两者都拖慢构建。
我的推荐起手式:
properties复制org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=1g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
6g 这个值怎么来的?不是拍脑袋,是观察出来的。我用 JVisualVM 挂过构建进程,大多数中大型 Android 项目的构建峰值堆占用在 4g 左右,留出 50% 余量到 6g 就足够了。
真正影响 GC 停顿的,往往是垃圾回收器的选择。Gradle 从 7.x 开始默认启用了 G1GC,但我实测下来,
