放弃 SDKMAN!在 Garuda Linux + Fish 环境下的优雅 Java 管理指南
作为一名长期折腾 Linux 的开发者,给系统配置开发环境简直是家常便饭。最近,我准备在我的主力机上(Garuda Linux,Intel i7-1260P,16GB 内存)搭建 Java 开发环境。
熟悉 Java 生态的朋友可能立刻会想到 SDKMAN 。作为一个老牌的多版本管理工具,它确实强大。我也理所当然地打开终端,准备通过 AUR 把它请进我的系统。但就在敲下安装命令的前一秒,我看着我那花里胡哨且极为顺手的 fish (4.5.0) 终端,突然意识到一个致命问题:SDKMAN 和 Fish 天生八字不合。
今天这篇博客,就来聊聊在 Arch 系(特别是使用 Fish Shell)的环境下,如何优雅、无痛地管理多个 Java 版本,以及我最终为何投入了 mise 的怀抱。
📍 我的现状与痛点
通过 fastfetch 可以看到,我当前的环境是高度定制化的:
- OS: Garuda Linux x86_64
- Shell: fish 4.5.0
- 需求: 需要安装并频繁切换不同版本的 JDK(如 Java 8, 17, 21),并且计划通过 AUR 安装管理软件。
痛点在哪? SDKMAN 原生是用 Bash 编写的,它的环境变量注入、别名和函数极其依赖 Bash/Zsh 的特性。而 Fish 是一个非 POSIX 兼容的现代 Shell,它不认识 Bash 的那些脚本逻辑。如果强行在 Fish 里用 SDKMAN,你会遇到命令找不到、环境变量丢失等各种让人抓狂的兼容性 BUG。
🛠️ 技术方案大比拼
在明确了痛点后,我梳理了三个可行的技术方案:
方案 A:Arch 官方纯正血统 archlinux-java
这是 Arch 系发行版自带的系统级工具。
- 原理: 直接通过
pacman安装官方仓库里的 JDK,然后用archlinux-java切换/usr/lib/jvm/default的系统软链接。 - 优点: 极度稳定,不用折腾任何第三方管理软件,速度最快。
- 缺点: 它是全局切换 的。如果你有两个项目,一个必须用 Java 8,一个必须用 Java 21,你每次进目录都得手动
sudo敲命令切换,非常繁琐。
方案 B:头铁硬上 SDKMAN + 兼容层
非要用 SDKMAN 也不是不行。
- 原理: 通过 AUR 安装 SDKMAN,然后再通过 Fish 的插件管理器(如 Fisher)安装
sdkman-for-fish这种第三方包装器(Wrapper)。 - 优点: 保留了原汁原味的 SDKMAN 习惯。
- 缺点: 架构臃肿。相当于在 Fish 外面包了一层 Bash 兼容层,不仅拖慢终端启动速度,日后出 BUG 排查起来也极为头疼。
方案 C:拥抱未来 mise(最终选择)
mise(前称 rtx)是用 Rust 编写的下一代开发环境管理器。
- 原理: 它通过修改
PATH环境变量,在命令执行前拦截并重定向到你指定版本的二进制文件。 - 优点: 速度极快(Rust 编写)、原生完美支持 Fish、支持按目录自动切换版本、不仅能管 Java,还能管 Node, Python, Go 等几乎所有语言!
🚀 mise 的安装与完全卸载指南
既然决定了用 mise,我们来看看如何操作。
1. 极简安装与配置
在 Garuda/Arch 下,AUR 提供了极其方便的打包:
Bash
bash
# 使用 paru 或 yay 安装
paru -S mise
安装完成后,只需要在 Fish 配置文件中加一行代码,让它接管环境:
Bash
bash
# 写入 Fish 配置文件
echo 'mise activate fish | source' >> ~/.config/fish/config.fish
重启终端,mise 就准备就绪了。
2. 如何完全卸载 mise?
如果你用了一阵子觉得不喜欢,Linux 玩家的强迫症绝不允许留下一点垃圾。完全卸载需要以下几步:
Bash
bash
# 1. 卸载软件包
paru -Rns mise
# 2. 从 Fish 配置中移除初始化代码
# 打开 ~/.config/fish/config.fish,删掉 `mise activate fish | source` 这一行
# 3. 清理配置文件和缓存(极其重要!)
rm -rf ~/.config/mise
rm -rf ~/.local/share/mise # 这里存放着所有下载的 JDK 和其他语言版本
rm -rf ~/.local/state/mise
rm -rf ~/.cache/mise
执行完以上命令,你的系统就如同从未安装过 mise 一样干净。
💻 mise 使用实战与小技巧
mise 的逻辑非常清晰,基本分为 全局(Global) 和 本地(Local) 两个概念。
基础用法:安装与切换 Java
安装并设置全局默认版本(比如 Java 21):
Bash
css
mise use --global java@21
就这一行命令,mise 会自动去清华源或官方源下载 JDK 21,解压,并设置为你的系统默认版本。执行 java -version 立刻就能看到效果。
为旧项目配置特定版本(比如 Java 8): 当你进入一个老旧的祖传项目时,只需要在项目根目录下执行:
Bash
perl
mise use java@8
这会在当前目录下生成一个 mise.toml(或 .tool-versions)文件。最神奇的地方来了 :以后只要你的终端 cd 进这个目录,Java 版本就会瞬间自动切换 为 Java 8;一旦 cd .. 离开,又会自动恢复成全局的 Java 21。全程无感,极其优雅!
💡 进阶使用小巧思
-
查看所有可用的 Java 版本: Java 发行版太多(Corretto, Temurin, GraalVM 等),你可以用
mise ls-remote java来列出所有可安装的版本。如果只想看特定的,比如 Temurin:Bash
perlmise ls-remote java | grep temurin -
清理闲置版本释放空间: 经常安装各种测试版本,磁盘(尤其是根目录)可能会爆。定期执行以下命令,
mise会自动帮你删掉那些已经安装但没有任何项目在使用的孤儿版本:Bash
mise prune -
兼容别人的
.tool-versions: 如果你的同事用的是asdf(另一个基于 Bash 的管理器),他们的项目里会有.tool-versions文件。别担心,mise默认兼容读取这个文件,你拉下代码直接就能用,连mise use都省了。
结语
在 Linux 下折腾环境,选择比努力更重要。对于 Arch 系 + Fish 这种前卫的组合,抛弃历史包袱较重的 SDKMAN,选择用 Rust 编写、原生支持各种 Shell 且性能炸裂的 mise,无疑是目前最完美的解决方案。
希望这篇记录能帮到同样在配置环境的你。你的主力开发环境用的是什么管理工具呢?欢迎在评论区和我交流!