java_home必须使用绝对路径,因为maven、gradle、tomcat等工具直接拼接路径且不解析相对路径,工作目录变更后相对路径立即失效;ide启动时读取系统级变量而非临时shell会话,容器和ci中亦同理。

环境变量里一般不能写相对路径,尤其是像 JAVA_HOME 这类关键变量——它必须用绝对路径。不是“怎么写才对”,而是“写了相对路径就错”。
为什么相对路径在环境变量中基本不可用
系统和工具链读取环境变量时,不会以你当前终端所在目录为基准去解析 ./jdk 或 ../java 这类写法:
- Maven、Gradle、Tomcat 启动脚本直接拼接
$JAVA_HOME/bin/java,不经过 shell 展开,也不识别点号或波浪号 - IDE(如 IntelliJ)启动时加载的是系统级环境变量,不是你某次
source的临时设置 - 新开终端、运行 CI 流水线、容器启动后,工作目录已变,
./jdk就彻底找不到 - Windows 注册表或 Linux 的
/etc/environment中填相对路径,会导致 java 命令根本无法定位 JVM
哪些地方可以安全用相对路径
相对路径真正起作用的地方,是程序内部的配置或运行时逻辑,而不是系统环境变量本身:
-
Log4j 配置文件中:用
${WORKDIR}/logs/app.log,再通过System.setProperty("WORKDIR", path)动态注入根路径 -
Tomcat 启动参数中:加
-Dmyapp.home="./myapp",然后在代码里用System.getProperty("myapp.home")读取 -
Spring Boot 配置文件中:比如
logging.file.path=logs,这个logs是相对于当前进程工作目录的 -
Vue 或前端构建配置中:
vue.config.js里的publicPath: './'或 axios 的baseURL: '/api',由浏览器按当前页面 URL 解析
如果非要“模拟”相对效果,推荐这几种做法
想让不同机器或环境少改配置?别硬塞相对路径进环境变量,换更可靠的方式:
- 用脚本自动推导绝对路径:比如在
setenv.sh中写JAVA_HOME=$(dirname $(dirname $(readlink -f $(which java)))) - 把 JDK 放到固定位置并统一约定:如所有 Linux 服务器都装在
/opt/jdk-17,Windows 都装在C:\Program Files\Java\jdk-17 - 用容器或包管理器(如 SDKMAN!、jEnv)管理 JDK 版本,它们内部维护的是绝对路径映射,对外屏蔽细节
- CI/CD 中用 setup-java action 或 apt/yum 安装后,直接读取它输出的绝对路径赋值给 JAVA_HOME
归根结底,环境变量是系统级契约,不是代码逻辑。它要稳定、明确、可预测——相对路径天生不符合这些要求。









