编辑
2025-12-21
工具
00

目录

告别手动配置:用 SDKMAN! 重塑你的 Java 开发环境
我之前的配置长这样
为什么是 SDKMAN!
安装与初始化
前置依赖
安装 SDKMAN!
目录结构
核心配置
日常使用
装一个 Java 版本
切换版本
查看当前状态
卸载
项目级版本锁定
生成配置文件
自动加载
纳入版本控制
从手动管理迁移过来
第一步:评估现状
第二步:用 SDKMAN! 装好需要的版本
第三步:清理 Shell 配置
第四步:删除旧的 JDK 文件
第五步:更新 IDE 配置
其他实用技巧
注册本地已有的 JDK
清理磁盘空间
离线使用
管理其他工具
常用命令速查
踩过的坑
sdk: command not found
切换版本后 IDE 里没变
公司网络装不了
写在最后

告别手动配置:用 SDKMAN! 重塑你的 Java 开发环境

写这篇文章的起因很简单——我受够了在 .bashrc 里维护一堆 JAVA_HOME_8JAVA_HOME_11 的日子。每次接手一个老项目要切 Java 8,改完配置还得 source 一下,偶尔忘了重开终端,构建失败查半天才发现是版本没切过来。

如果你也经历过这些,这篇文章应该能帮到你。


我之前的配置长这样

先看看我原来的 .zshrc(macOS)是怎么管理多版本 JDK 的:

bash
# JDK Config - 手动管理的噩梦 JAVA_HOME_8=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home JAVA_HOME_11=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home JAVA_HOME_17=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home export JAVA_HOME=$JAVA_HOME_8 alias jdk8="export JAVA_HOME=$JAVA_HOME_8 && java -version" alias jdk11="export JAVA_HOME=$JAVA_HOME_11 && java -version" alias jdk17="export JAVA_HOME=$JAVA_HOME_17 && java -version" CLASS_PATH="$JAVA_HOME/lib" PATH="$PATH:$JAVA_HOME/bin"

问题很明显:

  1. 路径硬编码——换台机器又得重新配
  2. 版本升级麻烦——17.0.1 升 17.0.2 要改路径
  3. alias 污染——项目多了 jdk8、jdk11、jdk17、jdk21... 一堆别名
  4. 新人上手难——入职新人还得手动下载、配置、踩坑一遍

后来我切换到 SDKMAN!,上面这些问题基本都解决了。


为什么是 SDKMAN!

市面上管理 Java 版本的工具不少,我对比过几个主流方案:

方案优点缺点
手动下载 + 环境变量完全可控繁琐,升级痛苦
Homebrew (macOS)安装方便多版本共存麻烦,cask 命名混乱
apt/yum (Linux)系统集成版本滞后,切换要用 update-alternatives
asdf多语言统一管理插件质量参差不齐,Java 支持一般
jEnv轻量只管切换,不管安装
SDKMAN!安装+切换一体,生态好仅限 JVM 生态

最终选 SDKMAN! 的理由很简单:它专注于 JVM 生态,而且真的好用。一行命令装 Java,一行命令切版本,还能顺带管理 Maven、Gradle、Kotlin、Spring Boot CLI。对于主力写 Java 的开发者来说,这就够了。


安装与初始化

前置依赖

SDKMAN! 的安装脚本需要 curlzipunzip,大多数系统都有,没有的话装一下:

bash
# macOS(通常已经有了,没有就用 Homebrew) brew install curl zip unzip # Ubuntu / Debian sudo apt update && sudo apt install -y curl zip unzip # CentOS / RHEL sudo yum install -y curl zip unzip

安装 SDKMAN!

一行命令:

bash
curl -s "https://get.sdkman.io" | bash

装完之后,要么重开终端,要么手动加载一下:

bash
source "$HOME/.sdkman/bin/sdkman-init.sh"

验证安装:

bash
sdk version # 输出类似:SDKMAN! 5.18.2

目录结构

装完后,SDKMAN! 的文件都在 ~/.sdkman/ 下:

~/.sdkman/ ├── bin/ # 可执行脚本 ├── candidates/ # 安装的工具(java、maven、gradle...) │ └── java/ │ ├── 17.0.11-tem/ # 具体版本 │ ├── 21.0.3-graal/ │ └── current -> 17.0.11-tem # 软链接,指向当前默认版本 ├── etc/ │ └── config # 配置文件 └── archives/ # 下载缓存

这个结构很清晰。current 是个软链接,sdk default 实际上就是改这个链接指向。


核心配置

配置文件在 ~/.sdkman/etc/config,默认配置就能用,但有两项建议改一下:

bash
vim ~/.sdkman/etc/config
properties
# 安装时自动确认,省得每次按 Y sdkman_auto_answer=true # 进入目录时自动加载 .sdkmanrc(后面会讲这个功能,很有用) sdkman_auto_env=true

改完不用重启,下次执行 sdk 命令时自动生效。


日常使用

装一个 Java 版本

先看看有哪些可选:

bash
sdk list java

会列出一大堆发行版——Temurin(原 AdoptOpenJDK)、Amazon Corretto、GraalVM、Oracle、Zulu... 选择困难症可能会犯,我的建议是:

  • 日常开发:Temurin(-tem),开源、稳定、更新及时
  • 生产部署:Temurin 或 Amazon Corretto(-amzn),都有商业支持
  • 尝鲜 / Native Image:GraalVM(-graal

安装很简单,版本标识从 sdk list java 里复制:

bash
# 安装 Java 17 (Temurin) sdk install java 17.0.11-tem # 安装 Java 21 (GraalVM) sdk install java 21.0.3-graal

安装时会问你要不要设成默认版本,选 Y 就行。

切换版本

两种切换方式,理解清楚区别:

bash
# 临时切换(只在当前终端生效,关掉就没了) sdk use java 21.0.3-graal # 永久切换(改默认版本,新开的终端都用这个) sdk default java 17.0.11-tem

我的习惯是:default 设成用得最多的版本(比如 17),临时需要用别的版本时用 use

查看当前状态

bash
# 看当前用的是哪个版本 sdk current java # 看所有工具的当前版本(如果你还装了 Maven、Gradle) sdk current # 看本地装了哪些 Java 版本 ls ~/.sdkman/candidates/java/

卸载

bash
sdk uninstall java 11.0.20-tem

项目级版本锁定

这是我觉得 SDKMAN! 最实用的功能之一。

场景:你同时维护三个项目——一个老项目用 Java 8,一个中期项目用 Java 11,新项目用 Java 21。每次切项目都要手动 sdk use 很烦。

解决方案:在项目根目录放一个 .sdkmanrc 文件。

生成配置文件

bash
cd ~/projects/legacy-system sdk env init

会在当前目录生成 .sdkmanrc

properties
java=8.0.412-tem

如果项目还用了特定版本的 Maven,可以手动加一行:

properties
java=8.0.412-tem maven=3.6.3

自动加载

如果你之前按我说的配置了 sdkman_auto_env=true,那么 cd 进这个目录时会自动切换:

bash
$ cd ~/projects/legacy-system Using java version 8.0.412-tem in this shell. $ cd ~/projects/new-system Using java version 21.0.3-tem in this shell.

如果没开自动加载,手动执行 sdk env 也行。

纳入版本控制

.sdkmanrc 提交到 Git:

bash
git add .sdkmanrc git commit -m "chore: pin Java version to 8 for legacy compatibility"

这样团队成员只要装了 SDKMAN!,clone 下来就能自动用对版本,不用再写文档说明"本项目请使用 Java 8"。


从手动管理迁移过来

如果你之前和我一样是手动配置的,迁移过程分三步:装新的、改配置、删旧的。

第一步:评估现状

先摸清楚你系统里装了哪些 JDK:

macOS

bash
# 系统目录 ls -la /Library/Java/JavaVirtualMachines/ # Homebrew 安装的 brew list | grep -i java brew list | grep -i jdk brew list | grep -i openjdk

Linux (Ubuntu/Debian)

bash
# apt 安装的 dpkg --list | grep -i jdk # 系统目录 ls -la /usr/lib/jvm/ # 手动装到 /opt 的 ls -la /opt/java/ 2>/dev/null

第二步:用 SDKMAN! 装好需要的版本

根据你原来用的版本,在 SDKMAN! 里装对应的:

bash
# Temurin 在 Apple Silicon 上没有 Java 8 sdk install java 8.0.412-tem # Azul Zulu 对 Apple Silicon 的 Java 8 支持最好 sdk install java 8.0.432-zulu sdk install java 11.0.23-tem sdk install java 17.0.11-tem sdk install java 21.0.9-tem # 设一个默认的 sdk default java 17.0.11-tem

验证一下:

bash
which java # 应该输出:/Users/你的用户名/.sdkman/candidates/java/current/bin/java java -version # 应该是你设的默认版本

第三步:清理 Shell 配置

打开你的 shell 配置文件(macOS 一般是 ~/.zshrc,Linux 一般是 ~/.bashrc):

bash
vim ~/.zshrc # 或 ~/.bashrc

删掉所有手动配置的 Java 相关内容:

bash
# 删掉这些 ↓ JAVA_HOME_8=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home JAVA_HOME_11=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home JAVA_HOME_17=/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home export JAVA_HOME=$JAVA_HOME_8 alias jdk8="..." alias jdk11="..." alias jdk17="..." CLASS_PATH="$JAVA_HOME/lib" PATH="$PATH:$JAVA_HOME/bin"

保留 SDKMAN! 的初始化代码(通常在文件末尾,安装时自动加的):

bash
# 这段保留 ↓ export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"

保存后重新加载:

bash
source ~/.zshrc

第四步:删除旧的 JDK 文件

确认 SDKMAN! 工作正常后,删掉旧的 JDK:

macOS

bash
# 删除系统目录的 JDK sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-1.8.jdk sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-11.jdk sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-17.jdk # 如果是 Homebrew 装的 brew uninstall --cask temurin brew uninstall openjdk@17 # ... 其他版本 brew cleanup

Linux

bash
# apt 装的 sudo apt remove openjdk-8-jdk openjdk-11-jdk openjdk-17-jdk sudo apt autoremove # 手动装到 /opt 的 sudo rm -rf /opt/java/jdk-17

第五步:更新 IDE 配置

IntelliJ IDEA 里的 JDK 路径也要改一下:

File → Project Structure → SDKs

把旧的删掉,加新的:

~/.sdkman/candidates/java/17.0.11-tem ~/.sdkman/candidates/java/21.0.3-graal

或者直接用 current 软链接,这样 sdk default 切换后 IDE 会自动跟随:

~/.sdkman/candidates/java/current

其他实用技巧

注册本地已有的 JDK

如果你有一个手动下载的 JDK(比如 Oracle 官方版,需要登录下载的那种),可以注册到 SDKMAN! 里统一管理:

bash
sdk install java oracle-21 /path/to/jdk-21

这样就能用 sdk use java oracle-21 来切换了。

清理磁盘空间

SDKMAN! 下载的安装包会缓存在 ~/.sdkman/archives/,时间久了会占不少空间:

bash
# 看看缓存占了多少 du -sh ~/.sdkman/archives/ # 清理 sdk flush archives

离线使用

在没网的环境(比如某些内网服务器),可以开启离线模式:

bash
sdk offline enable

当然,离线模式下没法安装新版本,只能用已经装好的。

管理其他工具

SDKMAN! 不只能管 Java,整个 JVM 生态都能管:

bash
sdk install maven 3.9.6 sdk install gradle 8.7 sdk install kotlin 1.9.23 sdk install springboot 3.2.5

用法完全一样。


常用命令速查

我把常用的命令整理了一下,可以存个书签:

bash
# ===== 版本安装 ===== sdk list java # 列出所有可装的版本 sdk install java 21.0.3-tem # 安装 sdk uninstall java 11.0.20-tem # 卸载 sdk install java mylocal /path/to # 注册本地版本 # ===== 版本切换 ===== sdk use java 17.0.11-tem # 临时切换(当前终端) sdk default java 21.0.3-tem # 永久切换 # ===== 状态查看 ===== sdk current java # 当前 Java 版本 sdk current # 所有工具的当前版本 sdk version # SDKMAN! 自身版本 # ===== 项目配置 ===== sdk env init # 生成 .sdkmanrc sdk env # 加载 .sdkmanrc # ===== 维护 ===== sdk update # 刷新可用版本列表 sdk selfupdate # 升级 SDKMAN! 自身 sdk flush archives # 清理下载缓存 sdk offline enable # 开启离线模式

踩过的坑

记录几个我遇到过的问题:

sdk: command not found

新开的终端窗口里 sdk 命令不存在。通常是 shell 配置文件里的初始化代码没加载。检查 ~/.zshrc(或 ~/.bashrc)末尾有没有这段:

bash
export SDKMAN_DIR="$HOME/.sdkman" [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"

切换版本后 IDE 里没变

IDE 有自己的 JDK 配置,不会跟着终端走。要么在 IDE 里手动改 SDK 路径,要么把 IDE 的 SDK 配置指向 ~/.sdkman/candidates/java/current

公司网络装不了

公司网络可能有代理。在 ~/.bashrc~/.zshrc 里加上代理配置:

bash
export http_proxy=http://proxy.yourcompany.com:8080 export https_proxy=http://proxy.yourcompany.com:8080

写在最后

从手动配置迁移到 SDKMAN! 之后,我的 .zshrc 里关于 Java 的配置从十几行缩减到了两行(就是 SDKMAN! 的初始化代码)。切版本从"改配置文件 → source → 验证"变成了一条命令。团队新人入职配环境从"看文档 → 下载 → 解压 → 配置 → 踩坑"变成了"装 SDKMAN! → 进项目目录 → 自动加载"。

工具的价值就在于此——把重复的事情自动化,把容易出错的事情标准化。

如果你还在手动管理 JDK 版本,不妨试试 SDKMAN!。