能,SDKMAN核心功能是多JDK版本共存与按需激活,各版本独立安装、互不干扰,需通过sdk use或sdk default显式切换生效。

SDKMAN能同时装多个JDK吗
能,而且这是它最核心的用途。SDKMAN不是版本切换工具,而是多版本共存+按需激活的环境管理器。它把每个JDK解压到独立目录(比如 ~/.sdkman/candidates/java/17.0.1-tem),互不干扰。
常见错误是以为装完就自动全局生效——其实装完只是“入库”,必须用 sdk use java 或 sdk default java 才会写入当前 shell 的 JAVA_HOME 和 PATH。
- 装新版本:执行
sdk install java 21.0.1-tem,不会覆盖旧版 - 查看已装:
sdk list java,带*的是当前 active 版本 - 临时切换:
sdk use java 17.0.1-tem,只对当前终端有效 - 设为默认:
sdk default java 21.0.1-tem,影响所有新打开的终端
为什么sdk use后java -version没变
大概率是 shell 配置没生效,或者你用的是非交互式 shell(比如 VS Code 终端、IDE 内置终端未重载配置)。SDKMAN 依赖你在 ~/.bashrc 或 ~/.zshrc 里 source 它的初始化脚本。
检查点:
立即学习“Java免费学习笔记(深入)”;
- 确认
~/.sdkman/bin/sdkman-init.sh已被 source:在~/.zshrc末尾应有类似source "$HOME/.sdkman/bin/sdkman-init.sh" - 改完配置后必须
source ~/.zshrc(或新开终端),否则sdk命令本身都可能报 command not found - 某些 GUI 应用启动的终端不会读
~/.zshrc,得手动在终端里执行一次sdk use -
java -version看的是PATH顺序,确保$JAVA_HOME/bin在 PATH 前部(SDKMAN 默认做到这点)
不同 JDK 供应商的版本名怎么选(tem、ibm、graalvm)
SDKMAN 列出的版本名里带短横线前缀,比如 17.0.1-tem、17.0.1-amzn、21.0.1-graalvm-jdk,这直接对应发行商和构建特性,不能随便省略或改写。
关键区别:
-
*-tem是 Eclipse Temurin(主流开源 OpenJDK 构建,推荐日常开发用) -
*-ibm是 IBM Semeru,企业级支持较多,但部分新 API 可能滞后 -
*-graalvm-jdk含 GraalVM 原生镜像能力,但启动慢、内存高,别当默认 JDK 用 -
*-j9(已基本淘汰)是 IBM J9 JVM,现在基本不用了
建议:除非项目明确要求某家 JDK,否则统一选 *-tem;升级时注意小版本号(如 17.0.2-tem)比大版本号(17.0.1-tem)更可靠,修复更多安全问题。
卸载旧 JDK 后JAVA_HOME还指向原路径
SDKMAN 不会自动清理系统级环境变量。如果你之前手动设过 JAVA_HOME(比如在 /etc/environment 或 ~/.profile),它会覆盖 SDKMAN 的设置,导致 sdk use 失效。
排查步骤:
- 运行
echo $JAVA_HOME,看输出是否来自 SDKMAN 目录(应是~/.sdkman/candidates/java/xxx) - 搜索全局配置:
grep -r "JAVA_HOME=" /etc/ ~/.profile ~/.bashrc ~/.zshrc 2>/dev/null - 删掉或注释掉所有硬编码的
JAVA_HOME=行,只保留 SDKMAN 的初始化逻辑 - 特别注意:Dockerfile、CI 脚本、IDE 的项目 SDK 设置,这些地方的 JDK 配置和 SDKMAN 无关,得单独改
SDKMAN 管理的是 shell 环境,不是操作系统全局状态。一旦离开终端上下文(比如 IDE 启动、systemd 服务、crontab),它就不起作用——这点最容易被忽略。










