环境变量是进程启动时的只读快照,终端重启才能加载最新值;因每个进程启动时复制一份环境变量副本,已运行终端不会自动更新,新开终端才会读取系统当前配置。

环境变量是进程启动时的快照,不是实时同步的
终端窗口(CMD、PowerShell、zsh、bash)在启动那一刻,会把当时系统的环境变量(比如 PATH、JAVA_HOME)完整复制一份作为自己的运行上下文。这个副本是只读的,后续你改了系统配置,它不会自动感知、也不会重新加载——就像拍了一张照片,原图再怎么修,照片也不会变。
为什么关掉再开一个终端就能生效
新开终端进程会重新读取当前最新的系统环境变量,自然就包含了你刚配好的 JAVA_HOME 和更新后的 PATH。这是最直接、最可靠的方式:
- Windows CMD/PowerShell:关闭旧窗口,点开始菜单或快捷方式打开新窗口即可
- macOS/Linux 终端:关闭标签页或窗口,再新建一个;如果用了
source ~/.zshrc,那只是刷新了当前终端的变量,不影响已运行的其他终端 - IDE 内嵌终端(如 VS Code 或 IDEA 的 Terminal):反复开关内嵌终端没用,必须完全退出 IDE 再重开——因为它的环境变量是从 IDE 主进程继承来的,而 IDE 启动时就固化了那一份
常见误判:以为 source 或 refreshenv 能全局生效
这些命令只对当前终端会话有效,不能影响其他已运行的进程,更不能“广播”给 IDE、Maven、Gradle 或后台服务:
-
source /etc/profile(Linux/macOS)或refreshenv(PowerShell)只能刷新当前终端的变量 -
which java和java -version输出不一致?说明which查的是PATH顺序,但实际执行的可能是/usr/bin/java这种被alternatives管理的软链接(尤其在 CentOS/RHEL 上) - IDE 显示 JDK 路径正确,但编译报错?检查
File → Project Structure → SDK是否手动指向了新 JDK,别依赖环境变量自动发现
真正容易被忽略的点
很多人重启终端后还是看到旧版本,问题往往不在终端本身,而在路径优先级或缓存残留:
-
PATH里混着多个 JDK 的bin目录,且老版本路径排在新版本前面 -
JAVA_HOME指向了jdk-17.0.2/bin,而不是jdk-17.0.2根目录(导致%JAVA_HOME%\bin实际拼成jdk-17.0.2/bin/bin) - Linux 下
/usr/bin/java是alternatives管理的软链接,source再多次也绕不过它——得用sudo alternatives --config java切换 - 某些 CI 工具(如 Jenkins)或 Docker 构建环境,根本不会读你的用户环境变量,得在脚本里显式设置











