在多项目并行开发的今天,A 项目用 Java 8,B 项目用 Java 17 已是常态。虽然 SDKMAN! 解决了”装”的问题,但”用”的过程依然不够优雅——每次进项目都要手动 sdk use,着实繁琐。
今天我们通过 SDKMAN + direnv 组合拳,实现进入项目目录即自动切换 JDK 的丝滑体验。
第一步:安装核心工具
工欲善其事,必先利其器。
1. 安装 SDKMAN!(JDK 管理器)
SDKMAN! 是类 Unix 系统上管理多版本 JDK 的最佳工具。
安装:
1 | curl -s "https://get.sdkman.io" | bash |
加载环境:
安装完成后,执行以下命令(或重启终端):
1 | source "$HOME/.sdkman/bin/sdkman-init.sh" |
验证:
1 | sdk version |
看到版本号即安装成功。
配置 Zsh 自动加载:
在 ~/.zshrc 末尾添加:
1 | export SDKMAN_DIR="$HOME/.sdkman" |
安装需要的 JDK 版本:
1 | sdk install java 25.0.2-tem |
2. 安装 direnv(环境加载器)
direnv 是一个轻量级 Shell 扩展,能根据当前目录自动加载/卸载环境变量。
安装(macOS):
1 | brew install direnv |
配置 Shell Hook(必做!否则不生效):
Zsh 用户在 ~/.zshrc 末尾添加:
1 | eval "$(direnv hook zsh)" |
第二步:打通 SDKMAN 与 direnv
direnv 默认无法直接调用 sdk 命令——因为 sdk 是 Shell 函数而非二进制文件。我们需要建一座桥。
创建全局辅助函数:
1 | mkdir -p ~/.config/direnv/lib |
这样所有项目都能复用这个函数。
第三步:项目级配置
有了全局配置,每个项目的设置只需几秒。
1. 生成 .sdkmanrc
在项目根目录执行:
1 | sdk env init |
这会生成 .sdkmanrc 文件,编辑为你需要的版本:
1 | java=25.0.2-graal |
2. 创建 .envrc
在项目根目录创建 .envrc:
1 | # 自动解析 .sdkmanrc 中的 java 版本号并切换 |
3. 授权生效
1 | direnv allow |
如果提示版本未安装:
1 | Stop! Candidate version is not installed. |
先执行安装命令,再重新 direnv allow。成功后会看到:
1 | Using java version 25.0.2-graal in this shell. |

4. 验证
1 | java -version |
确认输出的是你设置的 JDK 版本,大功告成!
SDKMAN 中的 JDK 版本设置简称
如果你同时安装了多个小版本,例如 17.0.1-tem、17.0.2-tem,那么每次执行 sdk use java ... 都要输入完整版本号,操作上会比较啰嗦。
SDKMAN 本身没有提供“别名”命令,但可以借助软链接实现一个足够实用的替代方案。
思路
在 ~/.sdkman/candidates/java/ 目录下,为某个真实版本创建一个自定义名称的软链接。这样 sdk 在切换版本时,就可以直接使用这个简称。
操作步骤
1 | # 1. 进入 SDKMAN 的 Java 安装目录 |
更新简称指向
当你想把 17 改为指向另一个具体版本时,可以先删除旧链接,再重新创建:
1 | rm 17 |
注意事项
- SDKMAN 没有原生的版本别名功能,软链接是一个简单直接的替代方案
- 自定义简称不能和已有的版本目录重名,否则会发生冲突
sdk use只对当前终端会话生效,sdk default会修改全局默认版本
结语
SDKMAN 负责管理安装,direnv 负责驱动环境——这套组合拳让 Java 版本管理变得极其丝滑。你只需专注于代码,版本切换这种琐事,交给工具就好。
以后每进入一个项目目录,JDK 自动切换,再也不用手动 sdk use 了。