在 Ubuntu 开发环境里,同时装着多个 JDK 是常态:老项目可能停在 Java 8,新项目已经用到 17,构建链路里还可能牵涉 Maven、Gradle 或 Spring Boot。真正麻烦的不是“装几个版本”,而是怎么稳定切换、怎么避免编译器和运行时不一致,以及团队项目里如何把版本约束落到目录级别。
这篇文章把 Ubuntu 下最常见的 3 种 Java 版本管理方式拆开讲清楚:只改系统默认值时用什么、按项目切换时用什么、连 Java 周边工具一起管时又该选什么。看完后,你可以根据自己的使用频率、项目数量和协作方式,判断该用 `update-alternatives`、`jenv` 还是 SDKMAN!。
为什么 Ubuntu 上经常需要管理多个 Java 版本
同一台开发机上共存多个 JDK,通常来自以下几类场景:
- 维护旧项目时仍需使用 Java 8 或 Java 11;
- 新项目已经切到 Java 17,甚至需要更高版本;
- 不同项目对运行时和编译器版本要求不同;
- 除了 Java 之外,还要顺手管理 Maven、Gradle、Spring Boot 等开发工具。
因此,版本管理的核心不是单纯“安装多个 JDK”,而是确保切换动作可控、验证方法明确,并且不会把 `java` 和 `javac` 切到不同版本。
用 update-alternatives 快速切换系统默认 Java
如果你的需求只是快速切换系统默认 Java 版本,不需要项目级隔离,也不想额外引入第三方工具,那么 Ubuntu 自带的 update-alternatives 已经够用。
先通过 apt 安装多个 JDK
常见做法是先安装多个 OpenJDK 版本,例如 8、11、17:
sudo apt update
sudo apt install openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk这种方式的优点是来源清晰、维护简单,适合作为系统基础版本池。
切换时记得同时处理 java 和 javac
安装完成后,执行下面的命令选择默认版本:
sudo update-alternatives --config java
sudo update-alternatives --config javac系统会列出当前可选版本,你只需要输入对应编号即可切换。这里最容易忽略的一点是:java 和 javac 要一起调整,否则运行环境和编译环境可能不一致。
切换后如何确认是否生效
完成切换后,建议立刻验证:
java -version
javac -version如果输出版本都符合预期,说明系统默认 JDK 已经切换成功。这种方式适合基础用户,也适合对“全局只保留一个当前版本”要求明确的环境。
用 jenv 做全局与项目级的精细化切换
如果你经常在多个项目之间切换,而且每个项目使用的 Java 版本可能不同,那么 jenv 会比系统级切换更灵活。它的重点不在安装 JDK,而在“管理已安装 JDK 的使用方式”。

安装 jenv 并初始化环境
jenv 的安装方式比较直接:
git clone https://github.com/jenv/jenv.git ~/.jenv
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(jenv init -)"' >> ~/.bashrc
source ~/.bashrc完成后,Shell 环境里就有了 jenv 命令。
把系统里的 JDK 路径加入 jenv
jenv 不负责替你下载 JDK,需要你把已经安装好的路径加入管理列表。例如:
jenv add /usr/lib/jvm/java-8-openjdk-amd64
jenv add /usr/lib/jvm/java-11-openjdk-amd64如果本机上还有其他版本,也可以继续用同样方式添加。
global 和 local 分别解决什么问题
jenv 的优势在于同时支持全局和目录级切换:
- 全局切换:
jenv global 1.8 - 项目目录切换:
jenv local 17.0
其中,jenv local 17.0 会在当前目录生成一个 .java-version 文件。这样当你进入该项目时,就能自动使用对应版本,对多人协作尤其有帮助。
如何查看当前到底在用哪个版本
可以先列出已接管的版本:
jenv versions带 * 的条目表示当前生效版本。之后再用下面的命令确认实际运行时:
java -version如果你重视项目隔离和频繁切换,jenv 往往比单纯改系统默认值更顺手。
用 SDKMAN! 同时管理 Java 与开发工具
当你的需求不止于 Java,而是希望顺手管理 Maven、Gradle、Spring Boot 等工具时,SDKMAN! 会更合适。它不仅能切换版本,也能统一负责下载、安装和卸载。
先安装 SDKMAN!
安装步骤如下:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"完成后即可直接使用 sdk 命令。
查看可用版本并安装指定发行版
先查看平台提供的 Java 列表:
sdk list java它会列出可安装的 OpenJDK、Oracle JDK 等版本。安装示例如下:
sdk install java 11.0.24-open
sdk install java 17.0.11-oracle这种方式适合需要跨发行版比较、或者需要特定厂商 JDK 的场景。
临时切换、设为默认和卸载都很直接
SDKMAN! 的日常使用也比较清晰:
- 临时切换:
sdk use java 8.0.422-open - 设置默认:
sdk default java 11.0.24-open - 卸载版本:
sdk uninstall java 17.0.11-oracle
如果你想把 Java 和其他 JVM 生态工具一起纳入同一套管理逻辑,SDKMAN! 的整体体验通常更完整。
怎么选工具,以及几个容易忽略的细节
三种方案分别适合谁
update-alternatives:适合只想切换系统默认版本的用户,依赖少,开箱即用。jenv:适合多项目开发,需要全局与项目级双重控制的场景。- SDKMAN!:适合除了 Java 之外,还要一并管理 Maven、Gradle、Spring Boot 等工具的开发者。
基础版本优先考虑官方源
通过 apt 安装的 OpenJDK 一般更稳定,也更适合作为系统里的基础版本来源。如果需要 Oracle JDK,可以通过 SDKMAN! 或手动下载安装包部署。

注意 JAVA_HOME 与当前版本保持一致
如果你的 IDE 或构建工具要求手动设置 JAVA_HOME,要确保它与当前实际使用的 Java 版本一致。可参考以下命令检查路径:
jenv prefix
update-alternatives --display java项目构建层也要声明 Java 版本
对于 Maven 或 Gradle 项目,仅靠本机切换版本还不够,最好在 pom.xml 或 build.gradle 中显式声明 Java 版本。这样即使团队成员本地环境不同,构建约束也更清楚,自动化流程也更稳定。









