
1. 为什么你的 Gradle 构建慢得让人想砸键盘如果你在国内做 Android 或者 Java 后端开发大概率经历过这种场景新建一个项目点下 Sync Now然后泡杯咖啡回来发现进度条还卡在 “Downloading gradle-x.x.x-all.zip” 上。再等一会儿直接给你弹一个Could not install Gradle distribution from ... Reason: java.net.SocketTimeoutException。这不是你网络的问题也不是电脑配置的问题这是 Gradle 默认的 distributionUrl 指向了国外的 CDN 节点国内访问那个地址的体验基本等同于抽奖。Gradle 本身是一个基于 JVM 的构建工具它的核心工作模式是每个项目绑定一个特定版本的 Gradle WrapperWrapper 在首次构建时会去下载对应版本的 Gradle 发行包。这个发行包小的七八十兆大的超过一百五十兆。从国外源拉这个包速度慢不说还经常断流。更麻烦的是Gradle 在构建过程中还需要从远程仓库拉取大量依赖 jar 包默认走的是 Maven Central 和 Google 的仓库这些仓库在国内的访问速度同样不稳定。所以 “Gradle 国内环境加速配置” 这件事本质上要解决两个层面的问题第一是Gradle 发行包本身的下载加速第二是项目依赖包的下载加速。这两个问题的解决思路不同配置位置也不同很多人搞混了改了一个地方发现没效果就是因为没分清这两层。这篇文章适合所有在国内做 JVM 生态开发的工程师不管你是刚接触 Gradle 的新手还是已经用了几年但一直忍受慢速构建的老手。我会从原理讲到实操把每一个配置项为什么这么写、改了之后影响什么都掰开揉碎说清楚。下面直接进入正题。2. 搞懂 Gradle Wrapper 的下载机制再动手改2.1 distributionUrl 到底在哪里起作用很多人第一次尝试加速 Gradle是去改系统环境变量里的GRADLE_HOME或者全局的init.gradle结果发现新建项目该慢还是慢。原因很简单你改的地方和实际下载发生的地方不是同一个。每一个用 Gradle Wrapper 管理的项目根目录下都有一个gradle/wrapper/gradle-wrapper.properties文件。这个文件里有一行关键配置distributionUrlhttps\://services.gradle.org/distributions/gradle-8.4-bin.zip这行配置才是决定 Gradle 发行包从哪里下载的唯一依据。当你执行./gradlew build或者点 Android Studio 的 Sync 按钮时Wrapper 会先检查本地~/.gradle/wrapper/dists/目录下有没有对应版本的 Gradle如果没有就按照distributionUrl指定的地址去下载。所以加速的第一步就是把这个 URL 换成一个国内访问速度快的镜像地址。这里要注意一个细节distributionUrl里的冒号和斜杠是需要转义的写成https\://这种形式这是 Java Properties 文件的语法要求不转义的话解析会出问题。2.2 国内镜像地址怎么选目前国内有几个主流的 Gradle 发行包镜像源比较稳定的是腾讯云和阿里云的镜像。腾讯云的地址格式是这样的distributionUrlhttps\://mirrors.cloud.tencent.com/gradle/gradle-8.4-bin.zip阿里云的地址格式类似distributionUrlhttps\://mirrors.aliyun.com/macports/distfiles/gradle/gradle-8.4-bin.zip这里有一个选择上的经验腾讯云的 Gradle 镜像更新比较及时新版本发布后通常几天内就会同步阿里云的镜像有时候会滞后一些。但阿里云的优势在于它的 CDN 节点覆盖更广某些地区访问速度更快。我的建议是两个都试一下用curl命令测一下下载速度哪个快用哪个。还有一个细节值得注意Gradle 发行包分-bin和-all两种。-bin只包含运行时必需的二进制文件-all还包含源码和文档。如果你不需要看 Gradle 源码用-bin就够了体积小很多下载更快。Android Studio 默认生成的项目有时候会用-all你可以手动改成-bin能省不少下载时间。2.3 手动放置离线包的技巧如果你所在的环境网络实在糟糕连国内镜像都慢还有一个终极方案手动下载 Gradle 发行包放到 Wrapper 的缓存目录里。具体操作是这样的先看一眼gradle-wrapper.properties里写的版本号比如gradle-8.4-bin.zip。然后用浏览器或者下载工具从国内镜像站把对应的 zip 包下载到本地。接下来找到 Wrapper 的缓存目录在 Windows 上是C:\Users\你的用户名\.gradle\wrapper\dists\在 macOS 和 Linux 上是~/.gradle/wrapper/dists/。在这个目录下你会看到一个以 Gradle 版本号命名的文件夹比如gradle-8.4-bin进去之后还有一个哈希值命名的子文件夹再进去就是实际的下载内容。你需要把下载好的 zip 包放到这个哈希值文件夹里然后重新执行构建。Wrapper 检测到本地已经有对应的 zip 包就不会再去下载了。注意哈希值文件夹的名字每次可能不同最稳妥的做法是先让 Gradle 尝试下载一次等它创建好目录结构并开始下载后取消然后把你的离线包放进去替换掉那个不完整的下载文件。这个方法的优点是彻底摆脱网络依赖缺点是每次换 Gradle 版本都要手动操作一次。适合网络环境特别差或者需要批量部署多台机器的场景。3. 依赖仓库加速才是日常构建提速的关键3.1 为什么改了 distributionUrl 还是慢很多人改完distributionUrl之后发现第一次下载 Gradle 确实快了但日常构建还是很慢。这是因为 Gradle 发行包只在首次构建或者切换版本时下载一次而项目依赖包是每次添加新依赖、每次清理缓存后重新构建时都要下载的。Gradle 的依赖下载走的是repositories配置默认情况下Android 项目会用google()和mavenCentral()Java 项目通常用mavenCentral()。这些仓库的服务器都在国外国内访问速度很不稳定。解决这个问题的思路是把仓库地址替换成国内镜像。但这里有一个坑不是所有依赖都能在同一个镜像站找到。Google 的 Android 相关库、Maven Central 的 Java 库、还有 JitPack 上的第三方库需要分别配置对应的国内镜像。3.2 多仓库镜像的配置策略在build.gradle或者settings.gradle里仓库配置通常长这样repositories { google() mavenCentral() }要加速的话需要改成国内镜像优先原仓库作为兜底repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/central } maven { url https://maven.aliyun.com/repository/gradle-plugin } google() mavenCentral() }阿里云的 Maven 镜像覆盖了 Google、Central、Gradle Plugin 等几个主要仓库基本能满足大部分项目的需求。把镜像放在前面Gradle 会按顺序查找找到就停止找不到才去原仓库找。这里有一个实操心得gradle-plugin这个仓库很多人会漏掉导致构建时插件下载还是很慢。如果你的项目用了 Kotlin DSL 或者一些第三方插件一定要把gradle-plugin镜像加上。另外如果你用的是 Gradle 7.0 以上版本推荐在settings.gradle里用dependencyResolutionManagement来统一管理仓库配置而不是在每个模块的build.gradle里重复写。这样改一处就能全局生效dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/central } maven { url https://maven.aliyun.com/repository/gradle-plugin } google() mavenCentral() } }3.3 镜像仓库的优先级与兜底逻辑配置多个仓库时Gradle 的查找逻辑是顺序遍历找到第一个包含目标依赖的仓库就停止。这意味着如果把镜像放在前面大部分依赖都会从镜像下载速度快如果镜像里没有某个依赖Gradle 会自动去后面的原仓库找不会报错。但这里有一个性能上的考量如果镜像里没有某个依赖Gradle 需要先请求镜像、等待超时或返回 404再去请求原仓库。这个等待过程会拖慢构建速度。所以镜像仓库的选择很关键要选覆盖率高、响应快的。阿里云的 Maven 镜像覆盖率在同类产品里是比较好的但也不是百分之百。如果你发现某个依赖总是从原仓库下载可以单独为它配置一个仓库repositories { maven { url https://maven.aliyun.com/repository/public } maven { url https://jitpack.io content { includeGroup com.github.xxx } } }用content块来限定仓库的适用范围可以避免不必要的跨仓库查找提升构建效率。4. 全局配置与项目配置怎么选4.1 init.gradle 的全局加速方案如果你手上有多个项目每个都去改build.gradle很麻烦。这时候可以用 Gradle 的init.gradle文件来做全局配置。init.gradle放在~/.gradle/目录下Gradle 启动时会自动加载。你可以在这个文件里统一配置仓库镜像allprojects { repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/central } maven { url https://maven.aliyun.com/repository/gradle-plugin } } }这样所有项目都会默认使用这些镜像不需要每个项目单独改。但要注意如果项目自己的build.gradle里也配置了repositories两边的配置会合并项目级的配置优先级更高。init.gradle的另一个用途是配置 Gradle 的下载超时时间。默认的超时时间比较短网络稍微抖动就会失败。可以在init.gradle里加上System.setProperty(org.gradle.internal.http.connectionTimeout, 60000) System.setProperty(org.gradle.internal.http.socketTimeout, 60000)把连接超时和读取超时都设成 60 秒给慢速网络留出足够的缓冲时间。4.2 项目级配置的灵活性与优先级全局配置虽然方便但有一个问题不是所有项目都适合同一套镜像。比如有些项目依赖了某个只在特定仓库才有的库全局镜像里没有就会导致构建失败。所以我的建议是全局配置只放最通用的镜像项目级配置根据实际需要做补充。具体来说init.gradle里放阿里云的public仓库和gradle-plugin仓库这两个覆盖率最高。项目级的settings.gradle里再根据项目特点加上google、central等镜像。还有一个细节Gradle 的仓库配置是有优先级的。项目级配置会覆盖全局配置中同名的仓库但不会完全替换。也就是说如果全局配置了仓库 A 和 B项目级配置了仓库 C最终生效的是 A、B、C 三个仓库顺序是项目级的在前。4.3 配置生效的验证方法改完配置之后怎么确认镜像真的生效了最直接的方法是看构建日志。执行构建时加上--info参数Gradle 会输出详细的下载信息./gradlew build --info | grep -i download如果看到下载地址是maven.aliyun.com开头的说明镜像生效了。如果还是repo.maven.apache.org或者dl.google.com说明配置没起作用需要检查配置位置是否正确。另一个验证方法是清理缓存后重新构建./gradlew build --refresh-dependencies--refresh-dependencies会强制 Gradle 重新检查所有依赖忽略本地缓存。如果镜像配置正确你会看到依赖从镜像地址下载如果配置有问题就会看到从原仓库下载速度明显变慢。提示--refresh-dependencies会比较耗时不建议每次构建都加。只在验证配置或依赖版本有更新时使用。5. 那些年我们踩过的 Gradle 加速坑5.1 镜像地址失效与版本不匹配国内镜像站虽然稳定但偶尔也会出现同步延迟或者地址变更的情况。我遇到过好几次前一天还能用的镜像地址第二天就返回 404 了。这时候构建会直接失败报错信息通常是Could not resolve all dependencies或者Could not find xxx.jar。排查这类问题的第一步是确认镜像地址是否还能访问。用curl命令测一下curl -I https://maven.aliyun.com/repository/public/com/google/guava/guava/32.0.0-jre/guava-32.0.0-jre.pom如果返回 200说明地址正常如果返回 404 或者超时说明镜像有问题需要换一个地址。另一个常见问题是版本不匹配。比如你的项目依赖了guava:33.0.0-jre但镜像站只同步到了32.0.0-jreGradle 在镜像里找不到就会去原仓库找。这种情况下构建不会失败但速度会变慢。解决办法是等镜像同步或者临时把原仓库的优先级调高。5.2 缓存污染导致的诡异报错Gradle 的缓存机制很强大但有时候也会带来麻烦。如果你之前用原仓库下载了一半的依赖然后切换到镜像仓库Gradle 可能会因为缓存中的元数据不一致而报错。典型的报错是Could not find xxx.jar或者Unexpected end of file。遇到这种情况最有效的办法是清理缓存./gradlew cleanBuildCache rm -rf ~/.gradle/caches/modules-2/files-2.1/第一条命令清理构建缓存第二条命令清理依赖缓存。清理完之后重新构建Gradle 会从镜像重新下载所有依赖。注意清理依赖缓存会导致所有依赖重新下载第一次会比较慢。建议在网络状况好的时候操作。还有一个更隐蔽的缓存问题Gradle 会缓存依赖的元数据比如maven-metadata.xml如果镜像站更新了元数据但本地缓存还是旧的就会导致版本解析错误。这时候可以用--refresh-dependencies强制刷新。5.3 代理配置与镜像的冲突有些公司内网需要通过代理才能访问外网这时候 Gradle 的代理配置和镜像配置可能会冲突。典型的表现是配置了镜像地址但 Gradle 还是走代理去访问原仓库速度反而更慢。Gradle 的代理配置在gradle.properties文件里systemProp.http.proxyHostproxy.company.com systemProp.http.proxyPort8080 systemProp.https.proxyHostproxy.company.com systemProp.https.proxyPort8080如果镜像地址是内网可以直接访问的就需要把镜像地址加到代理排除列表里systemProp.http.nonProxyHostsmaven.aliyun.com|mirrors.cloud.tencent.com这样 Gradle 访问镜像时就不走代理访问其他地址时才走代理。配置的时候要注意nonProxyHosts用竖线分隔多个地址支持通配符。5.4 常见报错速查表报错信息可能原因解决方法Could not install Gradle distribution from ... SocketTimeoutExceptiondistributionUrl 指向国外地址或网络不通替换为国内镜像地址或手动放置离线包Could not resolve all dependencies镜像地址失效或依赖不存在于镜像中检查镜像地址可用性添加原仓库兜底Could not find xxx.jar缓存污染或镜像未同步清理缓存后重新构建或等待镜像同步Gradle DSL method not found: minSdkVersion()Gradle 版本与 Android 插件版本不匹配检查 gradle-wrapper.properties 和 build.gradle 中的版本号Deprecated Gradle features were used in this build使用了已废弃的 API根据提示逐步替换为新 API或暂时忽略You are applying Flutters main Gradle plugin imperativelyFlutter 项目的 Gradle 插件应用方式过时按照 Flutter 官方迁移指南改为声明式应用这张表里的报错前三个是加速配置过程中最常遇到的后三个更多是版本兼容性问题。但它们的共同点是都会让你觉得 “是不是我的加速配置有问题”。实际上很多时候加速配置本身没问题是项目本身的版本管理出了状况。6. 进阶技巧让构建速度再快一点6.1 开启 Gradle 构建缓存Gradle 的构建缓存可以把上一次构建的输出保存下来下次构建时如果输入没变直接复用缓存结果跳过实际构建过程。开启方式是在gradle.properties里加上org.gradle.cachingtrue构建缓存和依赖缓存是两回事。依赖缓存缓存的是下载的 jar 包构建缓存缓存的是编译、打包等任务的输出。两者配合使用效果最好。对于多模块项目构建缓存的收益特别明显。比如你改了 A 模块的一个文件B 模块依赖 A但 B 模块本身没改Gradle 可以直接从缓存里拿 B 的构建结果不用重新编译。6.2 配置 Gradle 守护进程与并行构建Gradle 守护进程是一个常驻后台的进程可以避免每次构建都重新启动 JVM。开启方式是在gradle.properties里加上org.gradle.daemontrue org.gradle.paralleltrue org.gradle.jvmargs-Xmx4g -XX:MaxMetaspaceSize1gorg.gradle.paralleltrue让 Gradle 并行执行多个模块的构建任务多核机器上效果显著。org.gradle.jvmargs调整 JVM 内存默认值通常偏小大项目容易 OOM。这里有一个经验值-Xmx设置成机器物理内存的 1/4 到 1/2 比较合适。比如 16G 内存的机器设成 4G 到 8G。设太大反而会因为 GC 停顿影响性能。6.3 离线模式的正确使用姿势Gradle 有一个离线模式加上--offline参数后Gradle 只使用本地缓存的依赖不发起任何网络请求。这个模式在没网或者网络极差的时候特别有用。但离线模式有一个前提所有依赖都已经在本地缓存里了。如果缺了任何一个依赖构建就会失败。所以正确的使用姿势是先在网络好的时候完整构建一次把所有依赖都下载到本地然后再用离线模式。Android Studio 里也可以开启离线模式在 Settings 的 Gradle 面板里勾选 “Offline work” 就行。但要注意开启离线模式后如果项目添加了新依赖构建会失败需要先关掉离线模式同步一次。6.4 版本目录与依赖锁定Gradle 7.0 引入了版本目录Version Catalog功能可以把所有依赖的版本号集中管理在libs.versions.toml文件里。这样做的好处是版本管理更清晰而且配合依赖锁定Dependency Locking可以确保每次构建用的依赖版本完全一致。依赖锁定通过dependencyLocking配置开启dependencyLocking { lockAllConfigurations() }开启后执行./gradlew dependencies --write-locks生成锁定文件。之后每次构建都会严格按照锁定文件里的版本解析依赖避免因为镜像站同步了不同版本导致构建结果不一致。这个功能在团队协作中特别有价值。以前经常出现 “我本地能构建你本地构建失败” 的情况很多时候就是因为依赖版本不一致。用了依赖锁定之后所有人的依赖版本完全一致构建结果也一致。7. 我的个人配置模板与实操建议经过多个项目的实践我总结了一套比较通用的配置模板。gradle-wrapper.properties里这样写distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists distributionUrlhttps\://mirrors.cloud.tencent.com/gradle/gradle-8.4-bin.zip networkTimeout60000 validateDistributionUrltrue zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/distssettings.gradle里这样配置仓库dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/central } maven { url https://maven.aliyun.com/repository/gradle-plugin } maven { url https://maven.aliyun.com/repository/public } google() mavenCentral() } }gradle.properties里加上这些性能相关的配置org.gradle.daemontrue org.gradle.paralleltrue org.gradle.cachingtrue org.gradle.jvmargs-Xmx4g -XX:MaxMetaspaceSize1g -Dfile.encodingUTF-8 org.gradle.internal.http.connectionTimeout60000 org.gradle.internal.http.socketTimeout60000这套配置在我经手的几个项目里表现都很稳定。首次构建时 Gradle 发行包从腾讯云镜像下载通常一两分钟就能完成依赖从阿里云镜像下载速度基本能跑满带宽。日常增量构建因为开了守护进程和构建缓存通常十几秒就能完成。最后分享一个排查问题的思路当你觉得构建慢的时候先用--profile参数跑一次构建Gradle 会生成一份性能报告告诉你时间花在了哪里。是依赖下载慢还是编译慢还是某个任务卡住了报告里一目了然。根据报告有针对性地优化比盲目改配置有效得多。另外如果你用的是 Android Studio可以在 Gradle 面板里查看每次 Sync 的详细日志。日志里会显示每个依赖是从哪个仓库下载的如果发现大量依赖还是从原仓库下载说明镜像配置需要调整。这个日志比命令行输出更直观排查起来更方便。