这个问题问到点子上了!知其然还要知其所以然,这才是高级工程师的思维。

一句话总结原理: update-alternatives 本质上是一个“符号链接(软链接)管理器”。它通过在系统里玩一个“三层套娃”的软链接游戏,让你用同一个命令(java)就能指向不同版本的真实程序。


用“接力棒”来理解

当你敲下 java -version 并回车时,系统其实经历了一场接力赛:

  1. 你敲的命令:java
  2. ↓
  3. 第1棒(PATH路径):/usr/bin/java ← 这是一个软链接
  4. ↓
  5. 第2棒(alternatives池):/etc/alternatives/java ← 这是另一个软链接(被切换的就是这里)
  6. ↓
  7. 第3棒(真正的程序):/usr/lib/jvm/java-17-openjdk-amd64/bin/java ← 真实文件

update-alternatives --config java 干的事,就是修改第2棒 /etc/alternatives/java 指向哪里。


用命令亲眼看看这个“套娃”

你可以在服务器上自己验证,执行这几条命令:

  1. # 看第1棒指向哪
  2. ls -la /usr/bin/java
  3. # 输出类似:/usr/bin/java -> /etc/alternatives/java
  4. # 看第2棒指向哪(这就是被切换的那个)
  5. ls -la /etc/alternatives/java
  6. # 输出类似:/etc/alternatives/java -> /usr/lib/jvm/java-17-openjdk-amd64/bin/java
  7. # 看第3棒(真实文件)
  8. ls -la /usr/lib/jvm/java-17-openjdk-amd64/bin/java
  9. # 输出:这就是个真正的二进制可执行文件

当你运行 sudo update-alternatives --config java 并选了 Java 21 之后,第2棒就变成了:

  1. /etc/alternatives/java -> /usr/lib/jvm/java-21-openjdk-amd64/bin/java

就这么简单! 第1棒永远不变,变的只是第2棒指向谁。


还有个“优先级”的隐藏玩法

你执行 update-alternatives --display java 会看到每个版本有个优先级数字:

  1. update-alternatives --display java
  2. # 输出类似:
  3. # java - auto mode
  4. # link best version is /usr/lib/jvm/java-21-openjdk-amd64/bin/java (priority 2111)
  5. # link currently points to /usr/lib/jvm/java-17-openjdk-amd64/bin/java (priority 1711)

优先级规则:

  • auto 模式(默认):系统自动选优先级最高的那个。你装了 Java 21(优先级2111),它比 Java 17(优先级1711)高,系统就自动切到 21。
  • manual 模式(你手动选了之后):你手动选了 Java 17,系统就乖乖听你的,不再自动切了。

用 PHP 工程师熟悉的方式类比

这玩意儿其实跟你熟悉的 Composer 的全局命令 或者 NVM(Node Version Manager) 思路一样:

工具 管理方式 本质
update-alternatives 修改 /etc/alternatives/ 下的软链接 系统级版本切换
nvm use 18 修改 ~/.nvm/current 的软链接 Node.js 版本切换
composer global 修改 composer 的 bin 目录指向 PHP 工具管理

总结

问题 答案
它改了什么? 只改了 /etc/alternatives/java 这个软链接的指向
为什么能全局生效? 因为 /usr/bin/java 永远指向 /etc/alternatives/java,所有用户都走这条路
会影响已运行的程序吗? 不会! 已经跑起来的 Java 进程用的是启动时加载的那个版本,切换只影响新启动的程序
能管理其他命令吗? 能!python、gcc、php 甚至 editor 都能用这玩意儿管