简介:该资源为 Gradle 5.6.2 的 all 发行包,面向 Java、Android 及后端开发中需要构建工具支持的开发者,尤其是仍在使用 5.x 系列、希望规避新版兼容性问题的项目团队。相比 5.6.1,此版本重点修复了两处问题:Gradle 5.6 及以上版本生成的 .classpath 文件中出现的重复条目,以及使用 Worker API 配合进程隔离任务时产生的内存泄漏,对依赖 Eclipse 构建配置或大量并行任务的工程尤为实用。压缩包为 zip 格式,体积约 134.42MB,包含完整的发行内容,解压后可直接用于本地依赖配置与离线环境搭建。已有 420 人学习下载,适合需要稳定构建链路、排查重复类路径条目或关注 Worker 进程内存占用的中高级开发者参考使用。
1. gradle-5.6.2-all.zip:为什么老项目宁愿手工装它也不用 wrapper
老项目迁移、构建机重装系统、隔离内网打正式包,这几种场景里我遇到过太多次同一种卡壳:构建脚本一行没改,机器上没有可用的 Gradle,wrapper 又因为网络策略拉不下来,最后整条流水线停在一个几十兆的 zip 上。gradle-5.6.2-all.zip 就是给这种情况准备的:它是 Gradle 5.6.2 的完整发行包,除了运行所需的 bin 和 lib,还带源码与 DSL 文档,解压即可用,不依赖构建时的在线拉取。适合维护 Gradle 5.x 老工程、需要在隔离环境复现构建、或者要给团队钉死一份工具链版本的人。它不新,但把它放对位置、把版本配平,能省掉半天翻日志。
2. all 与 bin 的选择:包里多出来的东西值不值那几十兆
2.1 两个包解压后到底差在哪
同一个版本号下,官方一般给两个包:gradle-5.6.2-bin.zip和gradle-5.6.2-all.zip。名字只差一个词,落到磁盘上差的是两棵目录树。bin 包是「能跑就行」的最小集合,all 包在它之上多塞了 Gradle 自身的源码和文档。解压后顶层都是gradle-5.6.2/,往下看才有区别。
| 目录 | bin 包 | all 包 | 作用 |
|---|---|---|---|
bin/ | 有 | 有 | gradle、gradle.bat启动脚本 |
lib/ | 有 | 有 | 运行时 jar,含内嵌的 Groovy、Kotlin 编译器等 |
init.d/ | 有 | 有 | 全局初始化脚本目录,机器级配置放这里 |
docs/ | 无 | 有 | DSL 参考、Javadoc、用户手册 |
src/ | 无 | 有 | 核心与内置插件的源码 |
如果你只是想让 CI 机器上有个gradle命令,bin 包完全够,体积还小一圈。真正值得为 all 包多花那几十兆的场景只有两类:一是团队里有人需要在 IDE 里按住 Ctrl 点进build.gradle的 DSL 方法看实现,没有src/就只能看到反编译的空壳;二是排查 Gradle 自身行为异常,比如某个 task 的输入输出快照算得不对,手上有源码可以直接对,不用去翻在线文档。
我一般的取舍是:开发机装 all,构建机和容器镜像装 bin。理由是 CI 上没人看源码,多出来的几十兆在镜像层里会被反复拉取,不划算。但如果是那种「一台机器上既跑构建又有人登上去调试」的小团队,统一装 all 更省心,不用为「为什么我这能跳转你那不能」扯皮。
2.2 JDK 边界:Gradle 5.6.2 能吃下 Java 8 到 Java 12
Gradle 5.6.2 这个版本号看着不起眼,兼容窗口其实卡得很死。它跑在 JVM 上,对 JDK 版本有硬性上限。跑构建用的 JDK 超出范围,报错信息往往跟 JDK 八竿子打不着,比如解析build.gradle时直接抛Unsupported class file major version,或者Could not determine java version from 'xx'。这时候盯着构建脚本改一天也没用,问题在 JDK。
| JDK 版本 | class 文件主版本号 | Gradle 5.6.2 能否作为运行 JDK |
|---|---|---|
| 8 | 52 | 可以 |
| 11 | 55 | 可以 |
| 12 | 56 | 可以,但属于该版本支持的上限 |
| 13 | 57 | 不行,会报 major version 57 |
| 17 | 61 | 不行 |
注意这里说的是「运行 Gradle 的 JDK」,不是「编译产物用的 target 版本」。前者决定 Gradle 自身能不能启动,后者由sourceCompatibility、targetCompatibility控制,两件事别混。见过有人在build.gradle里把targetCompatibility从 11 改成 8,试图修major version 57的报错,方向完全反了。
先确认当前 shell 用的是哪个 JDK,再决定要不要给 Gradle 单独指定一个:
# 看当前 shell 的 JDK,major 57 说明是 13,直接换掉 java -version 2>&1 | head -n 3 # 机器上装了多个 JDK 时,给 Gradle 单独钉一个,不影响系统默认 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 $JAVA_HOME/bin/java -versionJAVA_HOME是 Gradle 启动脚本读取的第一优先级来源,比PATH里的java更可靠。CI 上经常出现PATH指向 JDK 8、JAVA_HOME还留着镜像里 JDK 17 的情况,gradle -v输出的 JVM 一行就是用来抓这个的。
还有一种更省事的做法:不去动环境变量,直接在项目根目录的gradle.properties里写死:
# 项目级钉死 JDK,避免不同机器环境漂移 org.gradle.java.home=/usr/lib/jvm/java-8-openjdk-amd64这个属性的好处是跟着代码走,谁 clone 下来都一样;坏处是路径写死了,Windows 和 Linux 不能共用一份。所以我的习惯是只在 CI 的 Dockerfile 或机器级~/.gradle/gradle.properties里写,不进仓库。
2.3 解压前后各做一次校验
压缩包在传输中被截断,是离线安装最常见的翻车点。表现是unzip报unexpected end of archive,或者解压「成功」但lib/里少几个 jar,启动时报NoClassDefFoundError。这类问题不看校验值很难发现。
# 1) 校验完整性:和制包方给出的 sha256 逐位比对 sha256sum gradle-5.6.2-all.zip # 2) 只看压缩包清单,确认不是半包 unzip -l gradle-5.6.2-all.zip | head -n 20 # 3) 真正解压到目标目录,-q 静默、-d 指定落点 sudo unzip -q gradle-5.6.2-all.zip -d /opt/gradleunzip -l这一步比校验值更快,它会把归档里的条目列出来,顶层应该只有一个gradle-5.6.2/目录。如果看到一堆乱码文件名,大概率是在 Windows 上用图形工具打的包又转了一遍,或者下载时被内容分发节点塞了错误页面,直接重下。
-d的目标目录建议固定成/opt/gradle或D:\tools\gradle这种约定俗成的位置,后面配GRADLE_HOME和 CI 镜像都好写。别图省事解压到~/Downloads,等到半年后要清理磁盘,会把工具链一起删掉。
3. 三种落地方式:解压安装、wrapper 指向本地、内网共享
包拿到手只是第一步,怎么让它真正被构建用上,有三种差别很大的路径。选错路径不会立刻报错,但会在半年后的某次换机、某次 CI 扩容时集中爆发。
3.1 解压到固定路径并配进环境变量
这是最朴素的方式,适合开发机和长期存活的构建机。核心就三件事:解压到位、设GRADLE_HOME、把bin加进PATH。
# 解压到统一位置 sudo mkdir -p /opt/gradle sudo unzip -q gradle-5.6.2-all.zip -d /opt/gradle # 写进 shell 配置,登录即生效 cat >> ~/.bashrc <<'EOF' export GRADLE_HOME=/opt/gradle/gradle-5.6.2 export PATH=$GRADLE_HOME/bin:$PATH EOF source ~/.bashrc gradle -v参数说明:GRADLE_HOME本身不被 Gradle 启动脚本强制读取,它主要给人和外部脚本看,真正起作用的是PATH里那一项。所以经常出现「GRADLE_HOME设对了但gradle命令还是老版本」的情况,根因是PATH里另一条更靠前的路径胜出了。排查就一句which -a gradle,把全部候选列出来看顺序。
Windows 上我不用图形界面解压,Expand-Archive虽然能用,但对大包很慢:
# 目标目录先建好,Expand-Archive 不会自动创建多级父目录 New-Item -ItemType Directory -Force -Path D:\tools\gradle | Out-Null Expand-Archive -Path .\gradle-5.6.2-all.zip -DestinationPath D:\tools\gradle -Force # 机器级环境变量,写完要重开终端 [Environment]::SetEnvironmentVariable("GRADLE_HOME", "D:\tools\gradle\gradle-5.6.2", "Machine") [Environment]::SetEnvironmentVariable("Path", $env:Path + ";D:\tools\gradle\gradle-5.6.2\bin", "Machine")-Force是覆盖已有文件,重装同版本时必加,否则会停在确认提示上。机器级变量改完必须新开终端,当前窗口的$env:Path不会自动刷新,这个坑每次换机都要踩一遍。
3.2 让 wrapper 认本地包:把 distributionUrl 指到 file 协议
项目里带了gradlew,说明构建走的是 wrapper 机制。wrapper 的原理很简单:gradle-wrapper.properties里写一个下载地址,第一次执行时把 zip 拉到GRADLE_USER_HOME/wrapper/dists/下,解压,然后用解压出来的这份跑构建。既然只是个地址,就能指向本地文件。
# gradle/wrapper/gradle-wrapper.properties distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists # 关键行:指向内网文件服务或本地磁盘,不再走公网 distributionUrl=file\:///opt/dist/gradle-5.6.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists格式上有几个必须注意的点。file:后面是三个斜杠,第三个斜杠之后才是绝对路径;properties 文件里冒号属于键值分隔符,习惯上写成\:转义,虽然多数解析器容忍不转义,但不要冒险。Windows 下路径写法是file\:///D\:/dist/gradle-5.6.2-all.zip,盘符后的冒号同样要转义,这一点比 Linux 更容易写错,写完先跑一次./gradlew --version验证。
还有一个隐藏副作用:wrapper 的缓存目录名是根据distributionUrl算出来的哈希,URL 变了哈希就变。也就是说你把地址从公网换成file://之后,之前下好的那份缓存不会被复用,会重新解压一遍。反过来,如果你在http和https、末尾带不带斜杠之间来回改,机器上就会堆积好几份一模一样的 Gradle,每份几百兆。这个在下一条会展开。
3.3 内网共享:预置 dists 目录给整批构建机
公司内网通常有文件服务或者制品库,把 zip 挂在上面,distributionUrl指过去,所有构建机第一次跑的时候自动拉一次,之后走本地缓存。这是最省维护成本的方式,前提是那个地址长期稳定。
如果连文件服务都没有,纯离线环境,就直接手动构造缓存目录:
# 先跑一次,让它把目录结构建出来(会因为下载失败而中断,正常) ./gradlew --version || true # 找到 wrapper 为这个 URL 算出的哈希目录 ls -1 "$HOME/.gradle/wrapper/dists/gradle-5.6.2-all/" # 把 zip 拷进那个哈希目录,文件名必须完全一致 cp /media/usb/gradle-5.6.2-all.zip \ "$HOME/.gradle/wrapper/dists/gradle-5.6.2-all/<hash>/" # 再跑一次,wrapper 发现本地已有 zip 就不再下载 ./gradlew --version关键是文件名必须严格等于gradle-5.6.2-all.zip,wrapper 靠文件名和哈希双重匹配,改名成gradle-5.6.2-all(1).zip会被当成不存在,继续尝试下载。哈希目录名不用记,ls一下就有;如果有多个哈希目录,说明历史上有过多个不同的 URL,选最近修改时间的那个。
批量铺机器的时候,把整个~/.gradle/wrapper/dists目录打进基础镜像,比每台机器单独拉要快得多。代价是镜像体积上涨,所以我会在镜像构建的最后一步清理掉dists下的临时解压目录,只留 zip 和已解压的成品。
3.4 验证:不要只看 gradle -v
gradle -v只证明命令能跑,不证明这个版本能跑你的构建。完整验证要走三步:
# 第一步:确认版本号与 JVM gradle -v # 第二步:确认 wrapper 用的也是同一个版本,而不是系统里的另一个 ./gradlew --version # 第三步:跑一次真实构建,先在线暖缓存,再离线复验 ./gradlew assemble ./gradlew assemble --offline --info | tail -n 40第一步和第二步的输出必须一致。不一致的典型原因是项目里有 wrapper,但开发者习惯敲gradle而不是./gradlew,两套版本各跑各的,本地能过、CI 挂掉。第三步的--offline是照妖镜:所有依赖都命中本地缓存才能通过,只要有一个依赖没缓存就会明确报出坐标。第一次跑必须先在线,让依赖落进缓存,否则--offline必然失败,白折腾。
4. 版本配对:Gradle 5.6.2 能带得动哪些 AGP 与 JDK
单机装好只是开始,真正让人抓狂的是版本组合。Gradle、Android Gradle Plugin、JDK 三者之间是硬约束,任何一环超出范围,报错信息都不会直说「你版本不对」。
4.1 AGP 与 Gradle 的最低版本约束
Android 工程里,AGP 会在构建初期检查 Gradle 版本,低于要求就直接终止,报Minimum supported Gradle version is x.y.z。这张表我贴在工位上很久了:
| AGP 版本 | 要求的最低 Gradle | Gradle 5.6.2 是否满足 |
|---|---|---|
| 3.4.x | 5.1.1 | 满足 |
| 3.5.x | 5.4.1 | 满足 |
| 3.6.x | 5.6.4 | 不满足,会直接报错 |
| 4.0.x | 6.1.1 | 不满足 |
所以 Gradle 5.6.2 对应的舒适区是 AGP 3.4 和 3.5。如果你的工程写的是 AGP 3.6.x,要么把 AGP 降到 3.5.x,要么换成 Gradle 5.6.4 及以上,二选一,没有第三条路。硬改gradle-wrapper.properties里的版本号去凑,只会在下一个报错处继续卡住。
对应的build.gradle配置长这样:
// 根目录 build.gradle,插件版本和 Gradle 版本必须成对 buildscript { repositories { maven { url "https://repo.internal/maven-public/" } // 内网制品库优先 mavenCentral() } dependencies { // 3.5.x 是 Gradle 5.6.2 的安全区间 classpath "com.android.tools.build:gradle:3.5.4" } } allprojects { repositories { maven { url "https://repo.internal/maven-public/" } mavenCentral() } }仓库顺序有讲究。内网制品库放前面,是为了让依赖优先在局域网命中,公网仓库只做兜底。Gradle 5.x 的 Groovy DSL 里url "..."这种写法仍然有效,比url = uri("...")更符合那个年代的代码风格;如果你的工程已经在用 Kotlin DSL,就只能写url = uri("..."),两种 DSL 的写法不能混。
4.2 gradle.properties 里的那几个开关
gradle.properties是性能调优的主战场,也是最容易被复制粘贴污染的地方。网上抄来的一份配置里,经常混着几个在 5.6.2 上并不划算的开关。
# 堆内存给足,Android 工程 2G 起步,太小会频繁 Full GC org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 # 守护进程常驻,连续构建能省掉每次启动的 JVM 预热 org.gradle.daemon=true # 多模块并行,模块数少于 3 的工程开了反而更慢 org.gradle.parallel=true # 构建缓存,跨机器复用任务输出,CI 上收益最大 org.gradle.caching=true # 按需配置:5.x 时代和自定义插件冲突较多,我一般关掉 org.gradle.configureondemand=falseorg.gradle.jvmargs是最值得调的一项。默认堆偏小,Android 工程多模块一开就容易撞上Daemon will be stopped at the end of the build after running out of JVM heap,那是守护进程堆被打爆后自动重启,表现是构建时间忽长忽短,看着像玄学。把-Xmx提到 2048m 或 4096m 之后,这种抖动基本消失。
org.gradle.parallel要慎开。它在模块间没有依赖时才能真并行,小工程开了之后进程调度开销反而盖过收益。判断办法很简单:跑两次构建,看--profile生成的报告里 tasks 的执行时间线,如果并行度上不去,就关掉。
org.gradle.caching在 CI 上收益明显,前提是缓存目录被持久化。本地默认缓存在~/.gradle/caches/build-cache-1,容器里如果不挂卷,每次构建都是冷启动,开了等于没开。
4.3 依赖缓存与离线构建的边界
Gradle 5.6.2 的依赖缓存放在~/.gradle/caches/modules-2,快照版本默认缓存 24 小时。这个默认值在联调阶段很要命:明明对方刚推了新快照,本地拉到的还是昨天那份。
// 强制刷新快照依赖,联调期间临时加 configurations.all { resolutionStrategy { cacheChangingModulesFor 0, 'seconds' } }cacheChangingModulesFor只影响标记为 changing 的模块,也就是 SNAPSHOT 之类,对正式版本无效,所以不用担心把稳定依赖的缓存也一起废掉。这段配置别长期留在仓库里,联调结束就删,否则每次构建都去远端问一遍,白白拖慢速度。
离线场景下还有一个隐性依赖:init.d/里的全局脚本。如果机器上的~/.gradle/init.d/里有人放过自定义脚本,比如强制走内网仓库,那么同一个项目在不同机器上行为会不一样。排查「为什么这台机器能过那台不能」的时候,ls ~/.gradle/init.d/是我第一个敲的命令。
5. 避坑排查:五类线上翻车现场
5.1 解压后 gradle 命令不存在或 Permission denied
现象:unzip顺利完成,ls也能看到bin/gradle,敲gradle -v报Permission denied,或者 shell 提示command not found。
原因通常是压缩包的权限位在传输过程中丢了。用某些图形解压工具、或者经过一轮对象存储搬运之后,可执行位不保留,文件变成 644。另一种是PATH没生效,改了~/.bashrc但用的是zsh。
解决:先补执行位,再确认 shell 配置文件对不对。
# 补执行权限,递归覆盖 bin 目录下的所有脚本 chmod +x /opt/gradle/gradle-5.6.2/bin/* # 确认当前 shell 到底读的是哪个配置文件 echo $SHELL which -a gradle5.2 构建启动即报 Unsupported class file major version 57
现象:gradle -v正常,但一执行./gradlew assemble就抛Unsupported class file major version 57,堆栈指向 Groovy 或脚本解析阶段。
原因:运行 Gradle 的 JDK 是 13,而 Gradle 5.6.2 支持到 Java 12。57 就是 Java 13 的 class 文件主版本号。这不是脚本问题,改build.gradle一律无效。
解决:把JAVA_HOME指到 JDK 8 或 11,或者在gradle.properties里用org.gradle.java.home钉死。改完一定要重开终端,export在当前会话里才生效,很多「改了没用」其实是另一个终端窗口在跑。
5.3 wrapper 卡在 Downloading 不动,最后超时
现象:执行./gradlew后停在Downloading https://...gradle-5.6.2-all.zip,进度条长时间不动,最终Connect timed out或Read timed out。
原因:wrapper 的下载走的是distributionUrl指定的地址,内网环境访问不到公网,或者代理没有覆盖到 Java 进程。注意 Gradle 的下载由 JVM 发起,系统级的代理设置不一定被继承。
解决:把distributionUrl改成内网地址或file://,或者按 3.3 的方式把 zip 手工塞进dists对应哈希目录。改完记得先./gradlew --version验证,别直接跑完整构建,否则失败点会被后续的编译错误掩盖。
5.4 dists 目录堆了五六份 gradle-5.6.2-all,构建机磁盘打满
现象:构建机磁盘告警,一查~/.gradle/wrapper/dists占了十几个 G,里面躺着多份同名不同哈希的 Gradle。
原因:缓存目录名由distributionUrl完整字符串算出。历史上有人把地址在http和https之间切换过,有人复制配置时多带了一个末尾斜杠,还有人把file:///opt/...改成了file:///home/...。字符串不同,哈希就不同,缓存自然不复用。
解决:统一 URL 写法,然后清掉历史残留。清理有风险,先看清楚再删。
# 列出每个哈希目录的大小和修改时间,先诊断 du -sh "$HOME/.gradle/wrapper/dists/gradle-5.6.2-all/"*/ # 确认当前项目实际用的是哪一个(看最近修改时间) ls -lt "$HOME/.gradle/wrapper/dists/gradle-5.6.2-all/" # 删掉旧的,保留最近使用的那份 rm -rf "$HOME/.gradle/wrapper/dists/gradle-5.6.2-all/<旧hash>"5.5 脚本里的 task << 语法报 Could not find method leftShift()
现象:从更老的工程迁过来,build.gradle里写着task hello << { ... },一跑就报Could not find method leftShift() for arguments。
原因:<<是leftShift操作符的语法糖,Gradle 5.0 已经把它移除了,5.6.2 自然也不认。这是升级到 5.x 之后最常见的语法级不兼容,报错信息里只有方法名,没有任何「请改成 doLast」的提示。
解决:全部换成doLast,语义完全等价。
// 旧写法,5.x 上直接报错 // task printVersion << { println project.version } // 新写法 task printVersion { doLast { println project.version } }工程里这类历史遗留往往不止一处,我一般先全局搜<<,把.gradle和.gradle.kts都过一遍,一次性改完,避免改一处跑一次、来回折腾。
6. 版本锁定的核对清单:我每次换机都要走一遍的六步
工具链这东西,装一次能用半年,中间不会有人记得当初怎么配的。等到半年后换机器、扩 CI 节点,全靠回忆。所以我把「Gradle 5.6.2 落地」压成了一张六步清单,每一步都有一句可直接执行的命令,跑完就知道这台机器到底行不行。
| 步骤 | 检查点 | 命令 | 不通过时的处理 |
|---|---|---|---|
| 1 | 压缩包完整 | sha256sum gradle-5.6.2-all.zip | 重下,别试图修复 |
| 2 | 解压后目录正确 | ls /opt/gradle/gradle-5.6.2/bin | 检查是否解压出了双层目录 |
| 3 | 版本与 JVM | gradle -v | 看 JVM 一行是不是 8 或 11 |
| 4 | wrapper 一致 | ./gradlew --version | 与上一步输出比对版本号 |
| 5 | 缓存命中 | ls ~/.gradle/wrapper/dists/gradle-5.6.2-all/ | 多份就按 5.4 清理 |
| 6 | 离线可构建 | ./gradlew assemble --offline | 先在线跑一次暖缓存 |
第六步是最有价值的一步,也是最容易被跳过的一步。它的原理是让所有依赖解析都走本地缓存,任何一处没命中都会立即暴露,而不是等到 CI 上才炸。第一次跑必然失败,因为缓存是空的;在线跑一遍assemble把缓存填满,再跑一次--offline,如果还能过,说明这台机器的依赖是自洽的,切到隔离环境也不会翻车。
我自己的血泪经验是第 2 步。有一回解压到/opt/gradle,结果多套了一层同名目录,变成/opt/gradle/gradle-5.6.2/gradle-5.6.2/,GRADLE_HOME指向上一层,PATH拼出来是个不存在的路径,gradle -v报 command not found。当时我在网络和权限上排查了快一个小时,压根没往目录结构上想。从那以后,每台新机器上我都要先find /opt/gradle -maxdepth 2 -name "gradle" -type f看一眼真实路径,确认没有多套一层再配变量。希望帮到你。
本文还有配套的精品资源,点击获取