最近一周里,连着三个朋友跑来找我,说他们在 Ubuntu 上装 JDK 装到怀疑人生。有人是在 VMware 虚拟机里装了 Ubuntu,结果java -version怎么敲都报 command not found;有人是明明跟着教程下好了 JDK,配置完环境变量重启终端又失效;还有人更冤枉,apt 安装完之后发现 Java 版本是旧的,程序一跑就崩。说实话,JDK 安装本身并不复杂,但 Ubuntu 下的安装方式实在太多——apt、tar.gz 手动解压、SDKMAN,每种方式的适用场景、坑点、后续维护成本都不一样。这篇就把我自己这么多年在 Ubuntu 上装 JDK 的完整经验整理出来,从思路到实操,从验证到排查,尽量把每一步为什么这么做也讲清楚。不管你是刚接触 Linux 的新手,还是打算在虚拟机、云服务器、Docker 里铺开发环境的老手,照着这套流程走,应该能少走不少弯路。
1. 动手之前,先把 JDK 安装的整体思路理清楚
1.1 为什么在 Ubuntu 上装 JDK 这一步值得单独写一篇教程
先说个很多人没意识到的问题:JDK 安装这件事,在 Windows 上基本是一个套路——下载安装包、下一步下一步、配环境变量。但在 Ubuntu 下,方案一下子多出好几种,而且每种方案背后的逻辑完全不同。
最常用的就是 apt 直接安装,sudo apt install openjdk-17-jdk一行命令搞定。系统会自动帮你处理依赖、把 Java 命令软链到/usr/bin下面,后续升级也方便。但代价是版本选择不自由,你能装到什么版本取决于当前 Ubuntu 发行版的软件源里有什么版本。比如 Ubuntu 20.04 默认源里 OpenJDK 的最高版本就是 11,想装 JDK 17 就得手动加 PPA 或者换方案。
第二种是去 Oracle 官网或者镜像站下载 tar.gz 压缩包,自己解压、自己移动到/usr/local目录、自己配JAVA_HOME和PATH。这种方式最灵活,想装哪个版本就装哪个版本,Oracle JDK、OpenJDK、甚至华为毕昇 JDK 都随便挑。缺点是要自己承担环境配置的所有细节,JAVA_HOME写错一个字母、PATH里少配一个目录,都可能让 Java 命令失效。
第三种是使用 SDKMAN 这种版本管理工具。它特别适合需要在多个 JDK 版本之间来回切换的场景,装完以后一条命令切版本,跟 Node.js 的 nvm 是一个路数。但新手用起来容易懵,因为 SDKMAN 是装在家目录下的,如果没开代理或者网络不好,下载速度会很难看。
我为什么先讲思路而不是直接给命令?因为这些年帮人排查 JDK 问题的经验告诉我,大多数人安装失败或者装上之后环境混乱,根源都是没搞清楚自己用的是哪一种方案,然后混着用。比如先用 SDKMAN 装了一遍,又手动解压了一个 JDK 到/usr/local,最后JAVA_HOME指向一个版本、PATH里又混着另一个版本,不炸才怪。
1.2 安装前必须想清楚的三个问题
第一个是版本问题。JDK 有自己的 LTS 长期支持版本,目前主流的是 JDK 8、11、17、21。JDK 8 虽然老,但很多老项目、老框架还在用;JDK 11 是 Spring Boot 2.x 时代的标配;JDK 17 是当前最主流的长期支持版,Spring Boot 3 要求最低就是 17;JDK 21 是最新的 LTS,新项目建议直接上。我个人的建议是,没有历史包袱的新项目统一用 JDK 17 或 21,老项目维护则老老实实跟着项目需求走。
第二个是发行版选择。OpenJDK 和 Oracle JDK 在普通开发场景下几乎没有差别,但 Oracle JDK 提供了一些商业特性,比如 Java Flight Recorder 在老版本中受许可限制。对绝大多数人和公司来说,OpenJDK 就够了,这也是 Ubuntu 官方源里默认的版本。只有当你明确需要 Oracle JDK 的商业支持或者某些特定行为时,才考虑下载 Oracle 版本。
第三个是架构确认。现在 ARM 架构的设备越来越多,树莓派、部分云服务器、Apple Silicon 上跑的虚拟机,都可能是 ARM 架构。JDK 的安装包是区分 x64 和 ARM64 的,下载错了就等着报cannot execute binary file吧。这个问题在后面 Server 环境部署时尤其容易踩,别问我怎么知道的。
2. 安装前的准备工作与系统检查
2.1 确认你的 Ubuntu 版本和硬件架构
拿到一台全新的 Ubuntu 机器,别急着装东西,先把底摸清楚。我通常按顺序执行三条命令:
lsb_release -a uname -m df -hlsb_release -a查看系统版本,比如 Ubuntu 22.04 LTS 或者 24.04 LTS。uname -m看架构,输出x86_64就是 Intel/AMD 的 64 位,输出aarch64就是 ARM 64 位。df -h看磁盘剩余空间,JDK 安装包几百 MB,解压后又占一份空间,确定磁盘够用很重要。
为什么版本和架构这么重要?因为 apt 软件源的配置跟 Ubuntu 版本强绑定,不同版本的软件源里 JDK 版本差异很大。比如 Ubuntu 24.04 的源里 OpenJDK 默认已经到了 21,而 Ubuntu 20.04 的源里最高也就 11。如果你照着网上的教程直接在 Ubuntu 20.04 上执行apt install openjdk-17-jdk,只会得到一个“无法定位软件包”的报错。
架构的问题就更隐蔽了。有些同学在 Windows 上用 VMware 装 Ubuntu,默认是 x86_64 架构,下载 x64 的 JDK 没问题。但如果用的是树莓派或者某些 ARM 云主机,下载错了包,解压完执行java -version,系统直接告诉你cannot execute binary file: Exec format error,到了这一步再回头找正确版本,浪费时间不说,心态也挺受影响的。
2.2 更新软件源并检查是否已有 Java 环境
新机器上我习惯先跑一遍更新,把软件源刷新到最新状态:
sudo apt update sudo apt upgrade -yapt update是更新软件包索引,apt upgrade是升级系统里已有的软件包。这两步做完,后续安装新软件时因为源版本太旧而踩坑的概率就小很多。
然后检查系统里是不是已经装过 Java:
java -version javac -version which java正常情况下的报错是Command 'java' not found,这是最干净的状态。但更多时候你会遇到一些诡异的情况:java -version能跑,但是版本完全不是你想要的;或者/usr/bin/java存在,但实际上是个软链接,指向的却是另一个目录。
这里就要说一下 update-alternatives 机制了。Ubuntu 用update-alternatives来管理系统里的多版本同一软件,Java 也可以被它管理。如果你以前用 apt 装过 OpenJDK,后来又想手动解压一个新版本,两条线并行,/usr/bin/java这个软链接最终指向哪里就变得很关键。检查一下没有坏处:
update-alternatives --list java如果你确定机器上什么 Java 都没有,执行完之后会提示错误。如果列出了路径,说明系统里已经有 Java 了,这时候就要考虑是覆盖安装还是先卸载再安装。我的经验是,除非你清楚不同版本之间如何切换,否则一台开发机上同时装多个 JDK 只会给自己找麻烦。
3. 三种主流的 JDK 安装方式,按需选择
3.1 方式A:apt 安装,适合绝大多数普通用户
apt 安装是 Ubuntu 官方推荐的方式,也是我个人的首选。原因很简单:安装过程自动化,依赖关系明确,卸载干净,后续还能跟着系统一起升级。
以 Ubuntu 22.04/24.04 为例,安装 OpenJDK 17 的命令是:
sudo apt install openjdk-17-jdk -y安装完成后验证一下:
java -version javac -version这个方案最省心的地方在于,apt 会自动帮你完成所有环境配置。Java 的可执行文件被放进/usr/lib/jvm/java-17-openjdk-amd64/bin,然后在/usr/bin下创建软链接,你直接敲java、javac就能用,不需要手动设置JAVA_HOME。很多 IDE 和构建工具在找不到JAVA_HOME时会自动探测/usr/lib/jvm目录,所以即便你没配环境变量,IDEA、Maven、Gradle 也往往能正常识别。
但 apt 方案的缺点是版本选择受限。Ubuntu 22.04 源里的 OpenJDK 版本是 11 和 17,Ubuntu 24.04 源里则是 17 和 21。想装 JDK 8 的话,要么加第三方 PPA,要么用下面两种方案。另外,apt 装的 OpenJDK 是“官方编译版”,某些场景下和 Oracle 官方二进制包的性能表现会有细微差异,但绝大多数业务代码根本感知不到。
如果你想在 apt 方式下装多个 JDK 版本并自由切换,可以用update-alternatives配置:
sudo update-alternatives --config java sudo update-alternatives --config javac执行后会列出系统里所有已注册的 Java 版本,输入对应的数字就能切换。这个机制配合 apt 安装多个 OpenJDK 版本,体验非常顺滑。
3.2 方式B:tar.gz 手动安装,版本自由但细节多
当你需要特定 JDK 版本(比如 JDK 8 跑老项目,或者用 Oracle JDK 的特定小版本)时,apt 就不够用了。这时候去 Oracle 官网或者国内的开源镜像站下载 tar.gz 包,手动部署。
先去镜像站下载 OpenJDK 压缩包,这里以华为云镜像站为例,结构清晰、速度快,比 Oracle 官网那种需要登录才能下载的体验好太多:
wget https://mirrors.huaweicloud.com/openjdk/17.0.2/openjdk-17.0.2_linux-x64_bin.tar.gz然后执行解压和移动:
sudo mkdir -p /usr/local/java sudo tar -zxvf openjdk-17.0.2_linux-x64_bin.tar.gz -C /usr/local/java/ cd /usr/local/java ls -l解压完成后你会看到类似于jdk-17.0.2的目录,这就是 JDK 的安装根目录。接下来配置环境变量,编辑/etc/profile或者当前用户的~/.bashrc:
sudo vim /etc/profile在文件末尾追加:
export JAVA_HOME=/usr/local/java/jdk-17.0.2 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar保存退出后执行source /etc/profile让配置生效,然后验证:
java -version echo $JAVA_HOME手动安装最大的问题在于路径管理。我看到很多人把 JDK 解压到~/Downloads或者/home/xxx下面,然后用起来也没问题,但一旦你重装系统、清理家目录、或者切换用户,JDK 就失效了。建议统一放在/usr/local/java这样系统级的位置,一个机器上多个 JDK 版本也能并列管理,互不干扰。
另外,手动安装的 JDK 卸载起来比较麻烦,没有apt remove那种干净的卸载机制。你得自己删掉解压目录、清掉/etc/profile里的配置,再检查/usr/bin/java等软链接是否残留。
3.3 方式C:SDKMAN 安装,多版本切换利器
SDKMAN 本质上是一个 Bash 脚本工具,用来管理 JVM 生态里的各种 SDK,包括 Java、Groovy、Scala、Maven 等。它的好处在于:统一的命令接口、按用户隔离、任意切换版本。
先安装 SDKMAN:
curl -s "https://get.sdkman.io" | bash source "$HOME/.sdkman/bin/sdkman-init.sh"安装完成后查看可用的 Java 版本:
sdk list java输出会列出各发行商、各版本的 Java,标识installed的是本地已装的,标识installed以下带local的是本地自定义安装。安装指定版本:
sdk install java 17.0.2-open这个17.0.2-open就是版本标识符,可以在sdk list java输出中看到。安装完成后 sdkman 会自动帮你设置当前用户默认的JAVA_HOME和PATH。切换版本就一条命令:
sdk use java 11.0.12-open想永久把某个版本设为默认:
sdk default java 17.0.2-openSDKMAN 的原理其实不复杂:它在你的家目录下创建.sdkman/candidates/java目录,不同版本以不同子目录共存,然后通过修改当前 shell 环境变量来实现切换。因为是纯用户级的操作,不需要 sudo,也不会污染系统目录,特别适合个人开发机。
但 SDKMAN 有个明显的坑:国内网络环境下get.sdkman.io的下载速度可能惨不忍睹,而且 SDKMAN 本身下载 JDK 的源也是国外 CDN。如果遇到卡住不动或者下载失败的情况,可以考虑先配一个代理环境变量再执行安装命令。另外,SDKMAN 只在当前用户的 shell 环境里生效,如果你写了 systemd 服务或者用其他用户跑程序,JAVA_HOME还是会找不到。
3.4 三种方式的取舍对比
| 对比维度 | apt 安装 | tar.gz 手动安装 | SDKMAN 安装 |
|---|---|---|---|
| 安装复杂度 | 极低 | 中等 | 中等 |
| 版本选择自由 | 受限 | 完全自由 | 完全自由 |
| 多版本切换 | 支持,用 alternatives | 手动配 | 一条命令 |
| 卸载方便度 | 高 | 低 | 高 |
| 适用场景 | 新手、普通开发机 | 特定版本需求、生产环境 | 多版本频繁切换、个人开发机 |
个人建议:如果只是要一个能用且不折腾的 JDK,直接apt install即可。如果做生产服务器部署,建议下载官方 tar.gz 包手动部署到固定目录,可控性最强。如果是你个人的开发机且习惯频繁切换版本,那 SDKMAN 值得花 10 分钟装一下。
4. JAVA_HOME 与 PATH 配置,这一步决定能不能跑起来
4.1 环境变量在 Ubuntu 里的加载逻辑
很多人配置完环境变量后,一开新终端发现命令失效了,就开始怀疑人生。要理解这个问题,得先搞清楚 Ubuntu 的 shell 启动文件加载顺序。
登录 Ubuntu 终端后,Bash 会依次加载这些文件(以登录 shell 为例):
/etc/profile:系统级配置,对所有用户生效~/.profile:用户级配置,登录时加载~/.bashrc:用户级配置,每次打开新的交互式终端都会加载
非登录 shell(比如在终端里再敲一个bash)只加载~/.bashrc。这个细节非常重要,因为它直接影响你该把环境变量写到哪里。
如果你把JAVA_HOME写在/etc/profile里,那么只有登录 shell 才会读取,新的终端窗口可能会继承登录时的环境变量,但某些场景(比如通过 SSH 执行非交互命令)会漏掉。我的习惯是:系统级服务统一写在/etc/profile,个人开发环境的 JDK 配置写在~/.bashrc。因为~/.bashrc对每个交互式终端都生效,兼容性最好。
还有一点容易被忽略:/etc/profile里经常会有一段遍历/etc/profile.d目录的逻辑,这个目录下可以放独立的.sh文件来配置环境变量。这也是很多软件安装时自动把自己的环境变量写进去的原因。
4.2 配置 JAVA_HOME 的标准步骤
无论用哪种方式安装,最终都需要让系统知道JAVA_HOME指向哪里,PATH里要带上$JAVA_HOME/bin。
配置~/.bashrc的标准做法:
vim ~/.bashrc在文件末尾追加:
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH注意,JAVA_HOME的值要换成实际 JDK 安装目录。如果你用 apt 安装,可以先执行readlink -f $(which java)拿到真实路径,然后反推 JDK 主目录。如果你手动解压,路径就是你解压出来的目录名。很多人的JAVA_HOME配错就是没搞清这个原理,直接抄教程里的路径,结果自己的系统上根本没有那个目录。
配置完保存退出,然后执行:
source ~/.bashrc验证是否生效:
echo $JAVA_HOME java -version这里有个经验之谈:source只对当前终端有效。如果你配置完验证没问题,然后立刻开一个全新的终端,发现java -version又报错了,那大概率是你写成了~/.profile而不是~/.bashrc,或者系统默认的 shell 是 zsh 而不是 bash。
4.3 配置失败的典型表现与修正思路
环境变量配置的问题,我总结出几个高频场景:
第一个是JAVA_HOME指向了bin目录。正确做法是JAVA_HOME指到 JDK 的根目录,比如/usr/lib/jvm/java-17-openjdk-amd64,然后在PATH里写$JAVA_HOME/bin。如果你把JAVA_HOME写成/usr/lib/jvm/java-17-openjdk-amd64/bin,那么PATH就会变成/usr/lib/jvm/.../bin/bin,命令直接找不到。
第二个是export语句里带了多余的空格。比如export JAVA_HOME = /usr/lib/jvm/...,Bash 会把它当命令执行而不是变量赋值,结果报错JAVA_HOME: command not found。我见过不少次这个问题,基本都是手速太快敲出来的。
第三个是新终端不生效但当前终端正常。这种情况大概率是环境变量写在~/.profile而系统 Bash 是登录 shell 才读取。新开终端如果默认是非登录 shell,~/.profile就不会被加载。修正方法就是改到~/.bashrc。
第四个是PATH里没有包含$JAVA_HOME/bin。有些人只配了JAVA_HOME,没改PATH,执行java -version时系统找到的还是/usr/bin/java这个旧软链接,版本可能完全不对。所以每次配完,我习惯先用which java看一下系统实际用的是哪个路径下的 java,再决定是否有必要调整PATH的顺序。
5. 安装后验证与多版本切换实战
5.1 一套完整的验证命令清单
安装和配置完成后,别急着写代码。我把验证命令整理成一套流程,每次装完 JDK 就按这个过一遍,基本能确认环境是健康的。
# 1. 查看 Java 运行时版本 java -version # 2. 查看 Java 编译器版本 javac -version # 3. 确认 JAVA_HOME 指向 echo $JAVA_HOME # 4. 确认 java 命令的实际路径 which java # 5. 解析软链接最终路径 readlink -f $(which java) # 6. 查看 PATH 中是否正常包含 JDK 的 bin echo $PATH这里解释一下第 4、5 步的作用。which java告诉你系统当前用的是哪个路径下的 java 命令,但 Ubuntu 下/usr/bin/java通常是一个软链接,它最终指向哪里才是关键。readlink -f的作用是层层解析软链接直到真实文件路径,这样你就能直观地看到当前 java 命令到底来自哪个 JDK。
如果你配了JAVA_HOME但which java显示的路径不是$JAVA_HOME/bin/java,那说明你的PATH顺序有问题,或者/usr/bin下的软链接优先级更高。这时候你可以在 shell 里执行hash -r刷新命令哈希表,然后再次验证。
5.2 用 update-alternatives 和 SDKMAN 实现版本切换
前面分别提到了两种多版本切换方式,这里再具体展开一下使用场景和操作步骤。
apt 安装的方案里,如果系统里有多个 JDK,比如 OpenJDK 11 和 OpenJDK 17 共存,你可以用 update-alternatives 切换默认版本。执行的瞬间会有交互界面让你选择,直接输入数字回车即可:
sudo update-alternatives --config java sudo update-alternatives --config javac中间有个小技巧:javac也需要单独切换,很多朋友只配了java,结果 IDE 编译报错才发现javac还是旧版本。
SDKMAN 的切换就简单多了:
sdk list java sdk install java 17.0.2-open sdk use java 11.0.12-open sdk default java 17.0.2-opensdk use只在当前 shell 会话里临时切换,关掉终端就恢复默认。sdk default会修改~/.sdkman/config里的默认配置,对后续所有新开的终端生效。
有一点必须提醒:当你用 SDKMAN 切完版本后,JAVA_HOME会被 SDKMAN 自动改到它的安装目录下,这时候你在~/.bashrc里手动配置的JAVA_HOME就会失效。如果你同时用了两种方案,且手动配置写在后面加载,SDKMAN 的配置可能会被覆盖。总之,原则是:多版本切换就用方案自带的机制,不要又在手动配置里纠结。
5.3 让 IDEA 和 Maven 准确识别 JDK
配完 JDK 之后,很多人会接着装 IntelliJ IDEA 或者 Maven。这两个工具对 JDK 的识别逻辑不太一样,搞清楚能省不少事。
IDEA 在启动时会自动检测JAVA_HOME指向的 JDK 作为默认 JBR,但每个项目的 SDK 可以单独指定。进入 IDEA 的 Project Structure,在 SDKs 里可以手动添加 JDK 的路径,这时候系统里不管装了几个 JDK,只要路径对,都可以加进来。如果 IDEA 界面里显示 JDK 加载失败,先查一下是不是 JDK 目录权限问题,或者路径里有中文空格。
Maven 使用的是JAVA_HOME环境变量,如果JAVA_HOME没配好,执行mvn -version会提示找不到 Java。注意 Maven 读取的是启动 Maven 的那个终端进程的环境变量,所以即使你改了~/.bashrc,但没重启终端,Maven 也还是拿到旧值。解决办法就是重新打开终端或者source ~/.bashrc。
另外,在写 systemd service 或者 Docker 容器时,环境变量是单独配置的。Docker 镜像里用 apt 装的 OpenJDK,官方镜像已经帮你配置好了JAVA_HOME,直接跑没问题。但如果是在一个精简的基础镜像里手动安装 JDK,就需要在 Dockerfile 里显式设置:
ENV JAVA_HOME=/usr/local/java/jdk-17.0.2 ENV PATH=$JAVA_HOME/bin:$PATH6. 常见问题与排查技巧实录
6.1 高频问题速查表
把这些年遇到的高频问题整理成一张表,方便直接翻查:
| 问题现象 | 可能原因 | 解决办法 |
|---|---|---|
java: command not found | 未安装 JDK 或 PATH 未包含 bin 目录 | 确认安装方式,检查 PATH 配置 |
javac: command not found | 安装了 JRE 而非 JDK | apt 安装选-jdk后缀的包 |
执行java -version版本不对 | PATH 里存在多个 Java,优先级不对 | 用which java定位,调整 PATH 顺序 |
| 新终端窗口 java 失效 | 环境变量写在~/.profile而非~/.bashrc | 迁移配置到~/.bashrc或~/.zshrc |
| echo $JAVA_HOME 输出为空 | 环境变量未生效 | 重新执行source ~/.bashrc |
| apt 提示无法定位 openjdk-17-jdk | 软件源里没有该版本 | 先 apt update,或换 Ubuntu 版本 |
| 解压后执行报 cannot execute binary file | 架构不匹配 | 用uname -m确认架构,换对应包 |
| IDEA 里找不到 JDK | JDK 路径错误或权限不足 | 在 Project Structure 手动指定路径 |
| SDKMAN 下载 JDK 超时 | 网络访问国外源慢 | 配置代理后重新执行下载 |
6.2 我踩过的几个有点奇怪的坑
第一个坑是关于系统自带的 Java 和手动安装的 Java 混在一起。某次我在一台服务器上发现java -version显示的是 OpenJDK 11,但我明明记得自己装的是 JDK 17。排查半天才发现,系统里之前通过 apt 装过一个旧版 OpenJDK,/usr/bin/java这个软链接一直指向旧版,而我新装的 JDK 17 只是解压到了/usr/local/java,PATH里新加的目录优先级又没有/usr/bin高。那次之后我养成一个习惯:手动安装 JDK 时先执行sudo update-alternatives --remove-all java清掉旧软链接,或者直接卸掉旧版本。
第二个坑是 Docker 容器里的 JDK 环境变量不生效。有次我用一个精简的 Ubuntu 镜像构建项目,在 Dockerfile 里写了ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64,结果容器启动后java命令还是找不到。后来发现这个精简镜像里根本没有/usr/lib/jvm,因为 Java 是在 RUN 阶段才 apt 安装的,但安装的路径并不一定是你预设的那个。正确做法是先跑一次which java和readlink -f确认路径,再写死到ENV里。
第三个坑是CLASSPATH的配置。有些教程会让你在配置里加export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar,但 JDK 9 之后模块化引入,dt.jar和tools.jar已经不存在了。我在老教程的影响下配过一次,结果编译时疯狂报 ClassNotFoundException。如果你用的是 JDK 9 以上版本,CLASSPATH一般不需要手动配置,反而配了容易出事。
第四个坑是卸载残留。有一次我apt remove openjdk-11-jdk之后,执行java -version还是能输出结果。查了下才发现/usr/lib/jvm目录还在,只是包管理器移除了二进制文件但没清理软链接和残留配置。所以卸载完 JDK 后,最好手动检查一下/usr/lib/jvm、/etc/profile、~/.bashrc里是否还有相关配置。
6.3 两个独家的小技巧
最后分享两个我平时非常依赖的小技巧。第一个是多版本并存时快速查看所有可用 JDK:
ls /usr/lib/jvm/ 2>/dev/null如果是 SDKMAN 管理的,就用:
ls ~/.sdkman/candidates/java/一眼看过去,系统里装了哪些版本清清楚楚,不会出现装完就忘了的情况。
第二个技巧是写一个setJava.sh脚本,放在/usr/local/bin下面,用来快速切换系统级 JDK 版本:
#!/bin/bash sudo update-alternatives --set java /usr/lib/jvm/java-17-openjdk-amd64/bin/java sudo update-alternatives --set javac /usr/lib/jvm/java-17-openjdk-amd64/bin/javac export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH虽然看起来很笨,但在生产服务器上做版本切换时,这种显式指定路径的方式反而最不容易出错,也方便同事接手维护。
结尾
回到开头说的那三位朋友,最后我给他们分别用的是不同的方案:一位只写 Java 测试程序,我让他apt直装 OpenJDK 17,省心;另一位要在老项目里用 JDK 8,我让他去镜像站下 tar.gz 手动解压到/usr/local/java;还有一位要在几个项目间频繁切换 JDK 版本,我帮他装了 SDKMAN。装完之后他们都说,原来没那么复杂,只是没有把思路理清楚。我自己这些年装 JDK 也有一个明显的变化:从早期迷恋各种配置技巧,到后来发现稳定和简单才是最重要的。如果你刚开始接触 Ubuntu 和 Java,建议先选定一种方案走通全流程,再慢慢尝试其他方案,没必要第一天就把环境搞得特别复杂。最后再分享一个小技巧:安装完一定顺手看一眼java -version和javac -version是否一致,很多所谓的“环境问题”,其实都是这两个版本对不上导致的。