「Java 装好了,java -version 也正常,就是程序读不到 JAVA_HOME」——这是 Ubuntu 配 Java 环境变量最高频的问题,根源在于环境变量有好几个生效范围,配错了层就白配。这篇把两种装法和三种配置层一起讲清楚。
一、先选装法
| 装法 | 适合 | 版本 |
|---|---|---|
apt install openjdk-21-jdk |
只需要一个版本、跟随系统更新 | Ubuntu 源里有的版本(22.04 有 17/21 等) |
| tar.gz 手动解压 | 要指定小版本、装多个 JDK、用 Oracle JDK/Temurin | 任意 |
生产建议 Temurin(原 AdoptOpenJDK)的 tar.gz,版本完全自己掌控。
二、装法一:apt(最快)
sudo apt update
apt search openjdk | grep -E "^openjdk-[0-9]+-jdk/" # 看有哪些版本
sudo apt install -y openjdk-21-jdk
java -version
apt 装完不需要配 JAVA_HOME 也能跑大部分东西,但很多 Java 工具(Maven 某些插件、IDE 远程调试、一些国产中间件)就是要读这个变量,所以还是配上(见第四节)。
三、装法二:tar.gz 手动装
# 以 Temurin 21 为例,去 adoptium.net 拿最新链接
cd /tmp
curl -fLO 'https://api.adoptium.net/v3/binary/latest/21/ga/linux/x64/jdk/hotspot/normal/eclipse'
sudo mkdir -p /opt/java
sudo tar -xzf eclipse-*.tar.gz -C /opt/java
ls /opt/java # 解出类似 jdk-21.0.x+x 的目录
四、配环境变量:选对层
三种配置位置,作用范围完全不同:
| 位置 | 生效范围 | 用途 |
|---|---|---|
/etc/environment |
全系统所有用户、包括 systemd 服务 | 服务器全局 JDK,推荐 |
~/.bashrc |
当前用户、仅交互式 shell | 个人开发机 |
/etc/profile.d/java.sh |
所有用户的登录 shell | 折中方案 |
服务器场景(推荐写法)
编辑 /etc/environment(这个文件是「KEY=值」格式,不要写 export):
JAVA_HOME="/opt/java/jdk-21.0.5+11"
然后把它加进系统 PATH——编辑 /etc/profile.d/java.sh:
export JAVA_HOME=/opt/java/jdk-21.0.5+11
export PATH=$JAVA_HOME/bin:$PATH
sudo chmod +x /etc/profile.d/java.sh,重新登录生效。
验证(重新登录后)
echo $JAVA_HOME
which java # 应指向 $JAVA_HOME/bin/java
java -version
五、为什么我配了却不生效(排查清单)
- systemd 服务读不到
~/.bashrc——它根本不走登录 shell。给服务配环境变量要写在 unit 文件里:
或者直接在[Service] Environment=JAVA_HOME=/opt/java/jdk-21.0.5+11/etc/environment里配(systemd 会读它)。 sudo默认重置环境变量——sudo java找不到时用sudo -E或在 sudoers 里配env_keep。- 只 export 没保存——当前会话有效,重开终端就没了,写进文件才是永久的。
- 改完没重新登录——
source ~/.bashrc只对当前终端有效,cron/服务进程完全感知不到。 - 路径写错——JAVA_HOME 指向 JDK 根目录(里面有
bin/),不是bin本身。
六、多版本切换
apt 装了多个版本(比如 17 和 21)时:
sudo update-alternatives --config java # 交互选默认 java
sudo update-alternatives --config javac
手动装的多版本更简单的做法:JAVA_HOME 固定指向一个软链:
sudo ln -sfn /opt/java/jdk-21.0.5+11 /opt/java/current
# JAVA_HOME=/opt/java/current,切版本只要改这个软链
sudo ln -sfn /opt/java/jdk-17.0.13+11 /opt/java/current
升级 JDK 时路径不变,所有引用 JAVA_HOME 的配置都不用动。
相关工具:Linux 命令速查 · SSH 连通性检测 · HTTP/Ping 检测