1. 为什么现在的 Mac 上还留着 JDK8 的位置
聊 MacOS 下载安装 JDK8 这件事,本身就带着一点“逆时代”的味道。毕竟 JDK 已经走到 20 多个版本,LTS 都换了好几轮,随便一个新项目脚手架拉下来,默认都是 17 或者 21。但只要你接过维护类的工作,或者手上有一批跑了五六年的老系统,就会发现 JDK8 像客厅里那张搬不走的旧沙发——占地方,可你还真得坐。我手上现在维护的三个服务里,有两个还是1.8.0_3xx的编译目标,本地要是没有 JDK8,连mvn clean package都过不去。
这篇内容写给三类人:第一类是刚换 Mac、准备搭 Java 开发环境的新人,看到网上教程五花八门,不知道该信哪个;第二类是接手了老项目的开发者,本地 JDK 版本跟项目对不上,编译报错一堆;第三类是需要在同一台机器上同时维护新旧项目的人,想让 JDK8 和 JDK17 和平共处。这三种场景的安装路径其实很不一样,尤其是最后一类,随便装一个很容易把默认版本搞乱,后面 IDE、Maven、Gradle 全跟着出问题。
我把整件事拆成了几个环节:先选对发行版和芯片架构,再选安装方式,然后是环境变量配置,接着是多版本共存,最后是踩坑排查。每一环都有几个容易被忽略的细节,我会把“为什么这么做”也一并说清楚,这样你换个环境、换个 JDK 版本,照样能自己推导出正确做法,而不是死记某一条命令。
1.1 老项目的现实约束
JDK8 在语法层面并不弱。Lambda 表达式、Stream 流式处理、方法引用、接口默认方法、Optional 以及全新的java.time日期时间 API,这些在今天依然是主力写法。很多团队迟迟不升级,不是因为不知道新版本好,而是升级成本太高:依赖的中间件客户端对高版本 JDK 的模块化限制不兼容,某些反射调用在 JDK9 之后会直接抛InaccessibleObjectException,老版本的 Lombok、ASM、CGLIB 在 JDK17 上编译期就崩。我见过最极端的一个项目,光是让 Spring Boot 1.x 跑在 JDK11 上,前前后后折腾了两周,最后结论就是继续用 JDK8。
所以“在 Mac 上装 JDK8”这件事,本质上不是一个技术选型问题,而是一个环境适配问题。你的目标不是追新,是让本地环境和生产环境、和团队其他成员的环境保持一致。这一点想清楚,后面很多选择就顺理成章了:既然是为了跑老项目,那就没必要追求最新版本号,稳定、好找、路径规范,比什么都重要。
1.2 三类不同诉求的人分别要注意什么
- 纯新人学习:重点是装一个能用的就行,别折腾多版本,路径记住一次即可。推荐用包管理器一把梭,省去手工配环境变量的麻烦。
- 维护老项目的开发者:重点是版本号要和线上尽量贴近。
1.8.0_202和1.8.0_402在大方向上兼容,但某些加密算法、TLS 协议默认值、时区数据库有差异,涉及这些逻辑的项目最好对齐。 - 新旧项目并行的人:重点是“不动全局默认版本”。你在
.zshrc里把JAVA_HOME写死成 JDK8,新项目那边立刻就能感受到恶意。这类情况必须上切换工具,或者至少在 IDE 和构建工具里做局部指定。
这三类人的路径不同,但有个共同点:都要先搞清楚自己要装的是哪个发行版、哪个架构。这部分内容是整个流程里最容易出错、也最容易被教程糊弄过去的地方。
2. 下载之前先做选择:发行版、版本号与芯片架构
很多人下载 JDK8 的第一反应是去某度搜“JDK8 下载”,点进第一个结果,下载一个不知道哪个机构打包的安装包。这个习惯得改。JDK 的发行版之间差异是实打实的,涉及授权、更新频率、架构支持、证书根签发方,装错了轻则keytool报错,重则整个构建链路的信任链对不上。
另外还要注意一个现实问题:MacOS 从 Catalina 开始就不再预装 Java 了,/usr/bin/java只是个转发器,第一次运行会弹窗让你去装运行时。所以你必须自己装一套完整的 JDK,而不是只装 JRE——javac、jar、keytool、jps这些工具在做开发时都会用到。
2.1 Oracle JDK 8 从哪个版本开始变了授权
这是一个绕不开的历史节点。Oracle JDK 8 从8u211 / 8u212开始,切换到新的授权协议,商用场景需要付费订阅。8u202 及之前的版本仍可以免费用于商业用途。这就是为什么你在网上会看到大量教程强调“认准 8u202”这个版本号。
实际操作里,8u202 有几个尴尬的地方:一是版本太老,发布于 2018 年底,之后的很多安全补丁拿不到;二是官网把他归到了归档页面,下载需要点好几个“接受协议”的勾选框,路径藏得比较深;三是在 Apple Silicon 的机器上跑 x64 版本的 8u202,需要额外装 Rosetta,而且实测启动速度确实一般。
我的建议是这样:如果是公司内部项目、法务那边卡得严,那就老老实实用 8u202 或者走 OpenJDK 系的开源发行版;如果是个人学习、开源项目、或者公司已经采购了相应的支持,那选社区维护的开源发行版更省心,补丁更新也更及时。这个判断你自己做,我后面会分别给出对应的下载和安装方式。
2.2 Temurin、Zulu、Corretto 横向对比
开源阵营里几个主流的选择,我整理成了下表,方便你按自己的场景挑。要注意的是,下面这些结论基于我实际使用和社区反馈的综合印象,具体某个小版本的行为还是以官方发布页为准。
| 发行版 | 维护方 | MacOS 支持情况 | 安装方式 | 适合场景 |
|---|---|---|---|---|
| Temurin | Eclipse Adoptium | 提供 Intel 与 Apple Silicon 包,具体见官网标注 | Homebrew Cask、pkg、tar.gz | 通用首选,社区生态好 |
| Zulu | Azul Systems | 对 Apple Silicon 支持较早,8 系列有对应包 | Homebrew Cask、tar.gz、pkg | M 系列芯片、需要旧版本 |
| Corretto | Amazon | 提供 macOS 安装包 | Homebrew Cask、pkg | 与云上环境保持一致 |
| Oracle JDK | Oracle | 提供 pkg,8u202 之后商用需授权 | dmg/pkg | 有订阅或有明确合规要求 |
选哪个其实差别不大,字节码层面都是标准 JDK,跑起来不会有兼容性问题。真正的差异体现在:一是证书库里的根证书集合略有不同,涉及 HTTPS 双向认证的项目要留意;二是某些版本对字体渲染、AWT/Swing 的处理有细微差别,做桌面应用的团队要测一下;三是更新节奏不同,有的跟随 Oracle 的季度更新,有的会滞后几个星期。
我个人在 M 系列 Mac 上的习惯是优先看官网页面有没有标aarch64或arm64,有就选它,没有就退回 x64 加 Rosetta。这不是玄学,原生的 arm64 版本在启动 JVM、编译大型项目时确实快一截,内存占用也更合理。
2.3 Intel 与 Apple Silicon:装错架构会怎样
这个坑我必须单独拎出来讲。MacOS 的芯片架构已经分成两代,uname -m在 Intel 机器上返回x86_64,在 M 系列上返回arm64。如果你在 M 系列机器上装了 x86_64 版本的 JDK,系统会静默调用 Rosetta 2 来翻译运行,表面上“能用”,但会带来几个后果:
一是启动变慢。JVM 冷启动那一下,翻译成本很明显,我实测过一个 Spring Boot 小项目,arm64 版本启动 1.8 秒左右,x64 版本要 3 秒多。二是内存占用偏高,Rosetta 的地址空间映射和原生不一样,长时间跑单元测试或者本地起服务,机器发热会明显一些。三是某些依赖本地库的场景会出问题,比如 JNI 调用、Netty 的 native transport、Lucene 的向量化指令集,架构不匹配时可能直接加载失败。
验证方法很简单,装完之后跑一下:
java -XshowSettings:properties -version 2>&1 | grep os.arch输出aarch64说明是原生 arm64,输出x86_64就是走 Rosetta 了。目录名上也能看出来,/Library/Java/JavaVirtualMachines/下面如果只有temurin-8.jdk这种干净的命名,需要进到Contents/Home里用上面那条命令确认。
3. 三种安装路径的完整实操
装 JDK8 这件事,MacOS 上大致有三条路:包管理器、官网 pkg、手动解压。三条路都能到达终点,区别在于可维护性、权限要求和出问题时的排查难度。我按推荐程度从上到下排。
3.1 Homebrew Cask:一条命令搞定
前提是机器上已经有 Homebrew。没装的先补上,安装脚本网上到处都是,这里不展开。装好之后,确认一下 Homebrew 本身是正常的:
brew --version brew doctorbrew doctor会给你一堆 Warnings,大部分可以忽略,只要不是明确报错的就行。接着安装 JDK8:
brew install --cask temurin@8想要其他发行版的话,包名对应关系是zulu@8、corretto@8。安装过程中可能会要求输入密码,因为要往/Library/Java/JavaVirtualMachines/里写文件。
装完之后验证:
/usr/libexec/java_home -v 1.8这条命令会打印出 JDK8 的家目录路径,类似/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home。能打印出来就说明系统层面已经识别到了。
Homebrew 这条路最大的好处是卸载干净。以后不用了,brew uninstall --cask temurin@8一条命令收拾利索,不会在系统里留一堆配置文件。缺点是版本号不完全由你控制,上游什么时候更新你就跟着更新,偶尔会遇到某个小版本跟你的老项目不太对付的情况,这时候可以用brew pin锁版本,或者干脆换手动安装。
注意:Cask 安装的 JDK 不带 Java 控制面板,也不改系统默认的
java指向。它只是把文件放到位,剩下的环境变量要你自己配。
3.2 官网 pkg 图形安装:最保险的做法
如果你需要指定某个精确的小版本号,比如必须用 8u202,那就得去官网下载 pkg 手动装。流程不复杂,但有几个细节容易翻车。
下载页面一般会按操作系统分类,选 macOS 之后会看到两种包:x64和aarch64。根据自己的芯片选。下载下来是个.dmg,双击挂载,里面有个.pkg,双击运行,一路下一步,中途会要求输入管理员密码。
装完之后同样用/usr/libexec/java_home -V确认一下。这里有个坑:如果你之前装过同系列的其他版本,pkg 安装可能会覆盖或者并存,java_home的管理机制是看目录下的.jdk文件夹,多个版本会都列出来,具体哪个生效取决于版本号大小和-v参数。
命令行安装 pkg 也是可以的,适合写自动化脚本的场景:
sudo installer -pkg /Volumes/JDK8/jdk-8u202-macosx-x64.pkg -target /这种方式的好处是版本完全可控,坏处是升级不方便,每次都得重新下载、重新装、手动清理旧版本。
第一次运行从官网下载的 pkg 时,可能会被 Gatekeeper 拦住,提示“无法打开,因为 Apple 无法检查其是否包含恶意软件”。处理方式是去“系统设置 → 隐私与安全性”,在最下面会看到刚才被拦截的条目,点“仍要打开”即可。这个提示跟包本身的安全性无关,只是签名验证走了另一条链路。
3.3 tar.gz 手动解压:没有 sudo 权限时的解法
公司电脑权限管得严、或者你只是想临时试一下,可以用 tar.gz 版本。下载下来解压到一个你自己有权限的目录,比如~/dev/jdk/:
mkdir -p ~/dev/jdk tar -xzf OpenJDK8U-jdk_aarch64_mac_hotspot_8u4xx.tar.gz -C ~/dev/jdk解压出来的目录名可能是jdk8u4xx-b07这种,为了方便识别,改个名:
mv ~/dev/jdk/jdk8u4xx-b07 ~/dev/jdk/jdk-8然后用export JAVA_HOME=~/dev/jdk/jdk-8就能用了。这种方式的坑在于,系统级的/usr/libexec/java_home认不到这个 JDK,因为它的扫描范围是固定的几个目录。如果你用的工具链依赖java_home(比如一些构建脚本、IDE 的自动探测),就会找不到。解决办法有两个:一是把解压后的目录通过符号链接放到/Library/Java/JavaVirtualMachines/下(需要 sudo),二是配好JAVA_HOME之后就不管java_home了,所有工具都显式指向。
手动安装的另一个好处是干净。整个 JDK 就是一个文件夹,不想要了直接rm -rf,不会在系统里留下任何东西。我本人在临时验证某个版本行为的时候,基本都用这种方式。
4. 环境变量怎么配才不会白装
JDK 装完只是把文件放到了硬盘上,终端里敲java -version能不能用、用哪个,完全取决于环境变量。这一步是新手最容易糊弄过去、也是后续问题最多的地方。
4.1 zsh 下到底改哪个文件
macOS 从 Catalina 开始默认 shell 换成了 zsh,对应的配置文件是~/.zshrc。但这里有个细节:zsh 会区分登录 shell 和非登录 shell,会按顺序读取.zshenv、.zprofile(登录时)、.zshrc(交互式)、.zlogin。图形界面启动的终端一般会读.zshrc,但从 Finder 或者某些 IDE 里启动的进程,环境来源可能完全不同。
所以我的做法是:把JAVA_HOME写在~/.zshrc里,同时也在~/.zprofile里写一份。两份内容一致,代价是维护成本略高,但能覆盖绝大多数场景。
编辑命令:
open -e ~/.zshrc用文本编辑器打开比用 vim 更直观,尤其是要往里粘贴多行配置的时候。改完保存,然后source ~/.zshrc让它立即生效。
4.2 写死路径与 java_home 动态取值
两种写法各有适用场景,我分别说。
写法一:硬编码路径
export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home export PATH=$JAVA_HOME/bin:$PATH简单直接,一眼就能看出用的是哪个版本。缺点是路径写死,某天你换了发行版或者改了目录名,就得回来改这一行。
写法二:动态取值
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) export PATH=$JAVA_HOME/bin:$PATH好处是路径由系统扫描得出,换发行版不用改配置。需要注意的是-v 1.8这个写法,不是-v 8,也不是-v 1.8.0。历史上 JDK 的版本号在 1.8 和 8 之间有个命名断层,java_home认的是1.8。如果机器上有多个 1.8 版本,它会返回版本号最高的那个。
还有一点,$(...)这种写法在每次打开终端时都会执行一次命令,会有几十毫秒的开销。可以接受,但如果你对终端启动速度特别敏感,可以改成硬编码。
注意:
PATH里$JAVA_HOME/bin必须放在前面。如果放后面,系统自带的/usr/bin/java那个转发器会先被匹配到,导致你敲java用的还是别的版本。
4.3 四条命令验证安装结果
配置完别急着关终端,跑一遍下面这几条,全部符合预期才算真的配好。
which java # 期望输出:/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/bin/java java -version # 期望输出:openjdk version "1.8.0_4xx" ... echo $JAVA_HOME # 期望输出:/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home javac -version # 期望输出:javac 1.8.0_4xx四条命令里,java和javac的版本号要一致,这是判断有没有装成“混血”的关键。有一种常见情况是:之前装过 JDK17,PATH里保留了它的路径,你又加了个 JDK8 的JAVA_HOME,结果java走的是 8,javac走的是 17,编译出来的 class 文件版本是 61,运行时报UnsupportedClassVersionError。这种问题排查起来费时间,一开始就检查清楚能省很多事。
5. JDK8 与新版 JDK 共存的切换方案
一台 Mac 上同时存在 JDK8、JDK17、JDK21,这是很常见的状态。麻烦在于“默认用哪个”。我见过有人为了图省事,每次切项目就去改一遍.zshrc,改完忘了 source,然后花半小时找为什么编译不过。这属于给自己制造工作量,有必要一次性解决。
5.1 手写一个切换函数
最轻量的做法,在.zshrc里加两个 alias:
alias jdk8='export JAVA_HOME=$(/usr/libexec/java_home -v 1.8) && export PATH=$JAVA_HOME/bin:$PATH && java -version' alias jdk17='export JAVA_HOME=$(/usr/libexec/java_home -v 17) && export PATH=$JAVA_HOME/bin:$PATH && java -version' alias jdk21='export JAVA_HOME=$(/usr/libexec/java_home -v 21) && export PATH=$JAVA_HOME/bin:$PATH && java -version'需要哪个版本就敲哪个,切换后会自动打印版本号确认。缺点是alias展开后修改的是当前 shell 会话的环境变量,开新终端会回到.zshrc里的默认值。这个行为其实是优点,能保证每个新终端有一个可预期的起点。
如果你想让切换更聪明,可以写成一个函数,按当前目录自动判断:
jdk_auto() { if [ -f .java-version ]; then export JAVA_HOME=$(/usr/libexec/java_home -v "$(cat .java-version)") export PATH=$JAVA_HOME/bin:$PATH fi }再配合 zsh 的chpwd钩子,cd到项目目录时自动切换。这个方案我在几个多项目并行的仓库里用过,体验不错,代价是每次cd都有一点点延迟,而且.java-version文件得记得维护。
5.2 jenv 的用法与代价
jenv是一个专门的版本管理工具,思路跟nvm类似。安装:
brew install jenv echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.zshrc echo 'eval "$(jenv init -)"' >> ~/.zshrc然后把你机器上所有的 JDK 注册进去:
jenv add $(/usr/libexec/java_home -v 1.8) jenv add $(/usr/libexec/java_home -v 17)之后就能用jenv global 1.8、jenv local 17来分别设置全局和目录级版本。其中jenv local会在当前目录生成一个.java-version文件,效果就是前面手动实现的那套逻辑。
jenv的代价有两个:一是它在JAVA_HOME外面包了一层 shim,某些工具(尤其是一些老旧的构建脚本或者 Docker 相关的插件)读取JAVA_HOME时可能会拿到 shim 目录而不是真实的 JDK 目录,导致识别失败;二是它会给每个 shell 会话增加一点初始化开销,如果你的.zshrc已经很臃肿,感知会比较明显。
我的态度是:项目多、切换频繁,用jenv值得;只是偶尔切一次,手写 alias 就够了。工具本身没有高下,看使用频率。
5.3 IDE 与 Maven 各自指定 JDK
这一条特别重要,而且经常被忽略。
IntelliJ IDEA里,JDK 的指定分成三个层级,别搞混:
Project Structure → Project → SDK:项目级别的默认 SDK,影响整个工程的编译和语言级别。Project Structure → Modules → Dependencies → Module SDK:模块级别,可以覆盖项目级别。Settings → Build Tools → Maven → Runner → JRE:Maven 运行时的 JRE,决定mvn命令用哪个 Java。
三层如果设得不一致,就会出现“IDE 里编译通过,命令行mvn package报错”或者反过来的情况。接手老项目时的标准动作就是先把这三处对齐。
命令行 Maven这边,mvn脚本会优先读JAVA_HOME,读不到才用PATH里的java。所以最省事的做法就是前面配好的 alias,切一次版本,IDE 里的 Maven Runner 也设成Use JAVA_HOME,两边就同步了。
Gradle更麻烦一点,它有org.gradle.java.home这个属性可以写在gradle.properties里,优先级高于环境变量。老项目里经常能看到这一行硬编码,换了机器路径对不上就报错。遇到这种情况,改掉它或者删掉让 Gradle 走环境变量。
6. 装完之后的常见报错与排查
以下问题都是我自己或者同事实际遇到过的,整理成速查的形式。表格里的“可能原因”按发生概率从高到低排。
6.1 安装环节的问题
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| pkg 双击没反应 | Gatekeeper 拦截 | 系统设置 → 隐私与安全性 → 仍要打开 |
| 安装时提示“需要管理员权限” | 账号不是管理员 | 用有管理员权限的账号,或用 tar.gz 方式装到用户目录 |
| Homebrew 安装卡在下载 | 网络问题或上游镜像慢 | brew --cache看缓存目录,手动下载后放入;或换用官网 pkg |
装完java_home找不到 | 目录名不以.jdk结尾 | 重命名为xxx.jdk形式 |
| 提示磁盘空间不足 | JDK 加 IDE 加缓存占了太多 | 清~/Library/Caches,检查 Time Machine 本地快照 |
6.2 环境变量与终端的问题
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
java -version还是旧版本 | PATH顺序不对 | 把$JAVA_HOME/bin提到PATH最前面 |
改了.zshrc但不生效 | 没source,或写错了文件 | 执行source ~/.zshrc;确认当前 shell 是 zsh |
| 新终端里变量丢失 | 写在了会话级而不是配置文件 | 写进~/.zshrc和~/.zprofile |
IDE 里读不到JAVA_HOME | GUI 启动不继承终端环境 | 在 IDE 设置里直接指定 JDK 路径,或用launchctl setenv |
java和javac版本不一致 | 多版本路径混在PATH里 | 用which -a java javac找出所有来源,逐个清理 |
关于 GUI 应用环境变量这一条,补充一句:从 Finder、Dock、Spotlight 启动的应用,环境变量来自系统登录会话,不读
.zshrc。所以你在终端里配好的JAVA_HOME,对图形界面启动的 IDE 是无效的。这是 macOS 上引发“终端能跑、IDE 不能跑”类问题最常见的原因。
6.3 运行与编译阶段的问题
| 报错信息 | 含义 | 处理方式 |
|---|---|---|
UnsupportedClassVersionError | class 文件版本高于运行时 | 检查编译和运行的 JDK 是否一致 |
NoClassDefFoundError: javax/xml/bind/... | JDK11 之后移除了 Java EE 模块 | 换回 JDK8,或在 JDK11+ 里加依赖 |
java.lang.reflect.InaccessibleObjectException | 模块化限制 | 加--add-opens参数,或换 JDK8 |
Unable to locate a Java Runtime | 只有转发器没有真 JDK | 装完整 JDK 并配好环境变量 |
Certificate chain not found | 证书库差异 | 用keytool手动导入缺失的根证书 |
6.4 卸载与清理
不用的 JDK 该清就清,尤其是那种装了七八个版本的机器,磁盘空间和排查成本都是实打实的。
# 查看系统识别到的 JDK /usr/libexec/java_home -V # 删除某个版本(路径来自上面命令的输出) sudo rm -rf /Library/Java/JavaVirtualMachines/temurin-8.jdk # Homebrew 安装的用这个 brew uninstall --cask temurin@8 # 顺手看一眼残留在系统里的安装收据 pkgutil --pkgs | grep -i jdk用 pkg 安装的版本,rm -rf删掉文件夹之后,收据信息可能还在,某些情况下会导致重新安装时提示“已安装”。这时候可以用sudo pkgutil --forget <包标识>清掉记录。Oracle JDK 还会在~/Library/Application Support/Oracle/Java和偏好设置面板里留东西,一起删掉更干净。
7. 几条实测下来的经验
折腾过十几台 Mac 的开发环境,有几个体会想单独说说。
第一,/Library/Java/JavaVirtualMachines/这个目录是 macOS 上 JDK 的“官方停车位”。不管用哪种方式装,最后都把 JDK 落到这里,能让java_home、IDE 自动探测、各种构建脚本都省心。手动解压的方案虽然干净,但代价就是脱离了这个体系,后面用工具的时候容易出意外。
第二,版本号别追求最新。JDK8 的小版本更新里,偶尔会有改动默认 TLS 协议版本、调整加密套件优先级这类行为,对老系统来说是不小的冲击。如果你的项目线上跑的是1.8.0_202,本地装1.8.0_4xx之前,先在测试环境验证一轮。我踩过一次,本地编译没问题,部署到测试环境之后某个 HTTPS 调用直接超时,查了半天才发现是本地 JDK 版本太新,默认开启的 TLS 版本变了。
第三,.jdk这个后缀名不是可有可无的。macOS 判断一个目录是不是 JDK,就是看它名字结尾是不是.jdk,然后再去Contents/Home下找bin/java。手动解压的目录如果叫jdk8u402,java_home完全不会认。这个规则没有文档明写,但实测有效。
第四,装环境这件事,能写脚本就别手敲。把brew install、环境变量、验证命令整理成一个setup.sh,换新机器的时候直接跑一遍,五分钟搞定。我现在的脚本里还带了卸载函数,反向操作也一并准备好,避免哪天真要清理的时候满系统找残留。
第五,M 系列芯片上跑老版本 JDK,如果遇到莫名其妙的崩溃或者 native 库加载失败,第一件事就是确认架构。java -XshowSettings:properties -version里的os.arch是最快的判断依据。如果是x86_64而机器是 arm64,那就考虑换一个原生版本,往往问题就消失了。
至于后续怎么扩展这套环境,看你的实际需求。有人需要在同一台机器上模拟多种 JDK 组合做兼容性测试,那就在~/.zshrc里多写几组 alias;有人要给团队做统一的环境配置文档,那就把整套流程写进 README,附上验证命令,让每个人装完自己跑一遍确认。这些都没有标准答案,按自己的场景来就行。