ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux下安装JDK完整指南:OpenJDK部署与环境变量配置实战

Linux下安装JDK完整指南:OpenJDK部署与环境变量配置实战 1. 写在前面的实话为什么一个安装教程还要专门写一篇我见过太多人在 Linux 下装 JDK 翻车了。明明 Windows 下点几下下一步就完事的东西换到 Linux 上各种花式报错bash: java: command not found、Error: could not open .../lib/amd64/jvm.cfg、明明配了环境变量但一开新终端就失效。更别提那些下载 JDK 还要登录 Oracle 账号的破事以及 CentOS 8 之后默认源里没有 JDK 8 的尴尬局面。其实 Linux 下装 JDK 这件事核心就三件事下载、解压、配环境变量。但每一件事都有无数个坑等着你。这篇东西不是为了凑字数我尽量把每个步骤背后的为什么讲清楚比如为什么推荐装 OpenJDK 而不是 Oracle JDK为什么JAVA_HOME要单独配而不是直接改PATH为什么~/.bashrc和/etc/profile选择哪个更好。把这些逻辑吃透了以后换任何发行版、装任何版本的 JDK你都能心里有数而不是靠背命令。这篇内容适合谁刚接触 Linux 的新手、要搭开发环境的运维同学、以及在各种国产系统上部署 Java 应用的工程师。看完之后你不仅能装好 JDK还能自己排查八成以上的环境问题。2. 动手之前先搞清楚这几个基本问题2.1 你的 Linux 是什么发行版、什么架构这一步很多人直接跳过结果后面全在折腾。不同发行版的包管理器不一样安装方式也不一样不同 CPU 架构对应不同版本的 JDK 安装包下载错了直接无法执行。先敲两个命令cat /etc/os-release uname -m第一个命令看发行版信息。如果是Ubuntu、Debian系列的包管理器是apt如果是CentOS、RHEL、Rocky Linux、AlmaLinux这些包管理器是yum或dnf如果是openEuler、麒麟、统信 UOS这类国产系统多半是基于 CentOS 或 Ubuntu 改造的处理方式基本兼容。第二个命令uname -m看架构。输出x86_64表示 64 位 x86 架构aarch64表示 ARM 架构loongarch64就是龙芯架构了。下载 JDK 时必须选匹配架构的包这一点比版本还重要版本选错顶多运行不了架构选错那是直接Exec format error。2.2 版本怎么选8、11、17、21 到底装哪个这不是拍脑袋的问题先看你的项目用什么版本。Spring Boot 3.x 要求 JDK 17 起步老一点的 Spring Boot 2.x 项目大多是 JDK 8而一些金融、政务系统现在还跑在 JDK 8 上。Oracle 从 JDK 8 之后每半年出一个新版本但只有 LTS长期支持版本适合生产环境目前主流 LTS 是 8、11、17、21。我的个人建议是新项目直接上 JDK 17老项目按需保持原有版本不要为了“用新版”盲目升级。升级 JDK 不只是换一个运行时那么简单Spring、Tomcat、MyBatis 这些框架的版本可能都得跟着动否则各种反射、代理报错会让你怀疑人生。一个常见需求是多版本共存。比如你一边维护老项目用 JDK 8一边新项目用 JDK 17那配置环境变量的时候就得花点心思后面我会专门讲怎么切换。2.3 备选方案对比OpenJDK 还是 Oracle JDK这个问题在 Linux 上其实没什么好纠结的。Oracle JDK 从 8u191 之后开始要求登录账号才能下载而且它的商业许可条款对生产环境使用有限制。OpenJDK 是完全开源免费的功能和 Oracle JDK 在绝大多数场景下没有任何可感知的差异。所以结论很直接日常开发、生产部署就用 OpenJDK。项目如果没有特殊合规要求完全没必要去折腾 Oracle JDK。另外还有几个常见的 OpenJDK 发行版值得了解Eclipse 家的 Temurin前身是 AdoptOpenJDK、Amazon 的 Corretto、阿里云的 Dragonwell它们都是经过各自生态验证的构建版本质量都靠得住。下载时优先从 OpenJDK 官方网站或清华大学镜像站、阿里云镜像站获取速度和稳定性都有保障。3. 三种主流安装方式手把手实操3.1 方式一包管理器安装最推荐适合绝大多场景包管理器安装最大的好处是省心它帮你处理下载、解压、路径规划、权限设置甚至环境变量都帮你配好了。Ubuntu 系用aptCentOS/RHEL 系用yum或dnf。Ubuntu/Debian 下装 OpenJDK 17sudo apt update sudo apt install openjdk-17-jdkCentOS/RHEL 系下装 OpenJDK 8sudo yum install java-1.8.0-openjdk-devel注意 CentOS 系的包名有个细节如果你只装java-1.8.0-openjdk那只是 JRE没有javac编译不了代码。必须带-devel后缀才会包含完整的 JDK 工具链。Ubuntu 的openjdk-17-jdk本身就包含开发工具但openjdk-17-jre就只有运行时别装错了。装完之后验证java -version javac -version如果输出版本信息说明已经装好了而且环境变量通常是自动配好的。你可以直接看readlink -f $(which java)这个命令会一路解析符号链接最终指向真实的 JDK 安装目录比如/usr/lib/jvm/java-17-openjdk-amd64/bin/java。这个路径后面配置JAVA_HOME会用到。但包管理器安装有个小缺陷发行版仓库里的 JDK 版本通常不是最新版。比如 Ubuntu 20.04 默认仓库的 OpenJDK 可能到 11 就到头了想要 17 得靠第三方 PPA 或者官方的 tar 包。所以如果项目有严格版本要求建议用下一个方式。3.2 方式二tar.gz 手动解压安装最灵活版本随心选这种方式适合需要特定版本、特定架构 JDK 的情况。比如 Ubuntu 20.04 想装 JDK 17或者生产环境要指定某个小版本号。第一步下载安装包。去 OpenJDK 官网或镜像站找到对应版本比如用清华镜像wget https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.12_7.tar.gz注意镜像路径的版本号和文件名会更新建议直接去页面里看最新版本再替换链接。下载完了习惯性验证一下sha256sum OpenJDK17U-jdk_x64_linux_hotspot_17.0.12_7.tar.gz把输出的哈希值和官网页面上公布的比对一下防止下载到损坏或篡改过的文件。第二步解压到指定目录。Linux 的惯例是把第三方软件放在/usr/local/下JDK 一般放在/usr/local/java/或者/opt/下sudo mkdir -p /usr/local/java sudo tar -zxvf OpenJDK17U-jdk_x64_linux_hotspot_17.0.12_7.tar.gz -C /usr/local/java/解压完后你会得到一个名为jdk-17.0.127的目录。为了后续升级方便建议做一个软链接让/usr/local/java/jdk-17指向当前版本目录cd /usr/local/java sudo ln -s jdk-17.0.127 jdk-17这样以后升级 JDK 的时候只需要把新的解压进去然后把软链接改一下指向就行环境变量完全不用动。这个习惯很多运维老手都有属于早期的“变量化”思想。第三步配置环境变量。这个下面单独用一大节讲。3.3 方式三rpm/deb 包安装适合发行版深度定制场景有些场景下你需要用.rpm或.deb格式的安装包来装 JDK比如公司内部有标准的软件分发流程或者你的系统有统一的包管理规范。安装.deb包sudo dpkg -i openjdk-17_linux-x64_bin.deb安装.rpm包sudo rpm -ivh jdk-17_linux-x64_bin.rpm这类包安装完通常会自动注册环境变量并且把二进制文件放到系统标准路径下。它们的安装位置一般会被管理工具自动记录卸载也会干净一些sudo dpkg -P openjdk-17 # 卸载 deb 包 sudo rpm -e jdk-17 # 卸载 rpm 包但这种方式有个劣势不太方便同时管理多个版本。所以如果你有频繁切换版本的需求tar.gz 方式依然是首选。4. 环境变量配置这才是真正的重头戏4.1 你需要理解环境变量在干什么而不是死记硬背很多教程上来就让你抄三行export但从来不解释为什么。结果你配完了一重启终端就失效再上网一搜又给你另一段配置越弄越乱。通俗讲环境变量就是在告诉操作系统三件事第一JAVA_HOME告诉系统 JDK 装在哪里它是后续很多 Java 生态工具的基线。比如 Maven、Gradle、Tomcat 都会通过这个变量去找 JDK如果你不配那些工具全会报错。第二PATH告诉系统去哪里找可执行命令。当你敲java的时候系统实际上是在PATH列出的各个目录里依次查找名为java的文件。所以PATH里加上$JAVA_HOME/bin就相当于告诉系统命令找不到的时候去 JDK 的 bin 目录看一眼。第三CLASS_PATH是 Java 类库的搜索路径。现代 Java 开发中这个变量大多数时候是多余的而且配错了反而容易出问题。很多老教程让你配CLASS_PATH$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar那是远古时代 JVM 9 之前的遗留做法现在的 JDK 根本不需要配了也不会有问题但完全没必要。4.2 配置文件该选哪个/etc/profile、~/.bashrc、/etc/profile.dLinux 下配置环境变量的位置有好几个很多人就在这里迷路了。/etc/profile是全局配置对所有用户生效但只要用户登录 shell 才会加载非交互式 shell比如执行脚本时不一定会加载。/etc/bashrc是全局的 bash 配置每次打开新的 bash 窗口都会加载。~/.bashrc是当前用户级别的配置灵活性最高只影响你自己不会干扰系统里其他用户。/etc/profile.d/*.sh是/etc/profile会遍历加载的目录很多现代软件安装后都会往这里丢一个.sh文件。我的建议很简单单用户开发环境用~/.bashrc生产服务器给所有用户用且希望一条命令全局生效用/etc/profile.d/java.sh。不建议直接改/etc/profile因为升级系统或安装其他软件时可能被覆盖而且改动会影响所有用户出问题排查范围更大。配置的命令是一样的无论是用哪个文件export JAVA_HOME/usr/local/java/jdk-17 export PATH$JAVA_HOME/bin:$PATH注意PATH那行前面的$JAVA_HOME/bin一定要放在$PATH之前这样系统会优先使用我们自己指定的 java 命令。如果你机器里还有其他地方也装了 JDK这种方式能确保当前 shell 用的就是你想用的那个。4.3 修改之后为什么不生效——source 的意义配置文件改完了当前 shell 并不知道。你需要让当前的 shell 重新读取这个文件source ~/.bashrc如果你是配在/etc/profile或/etc/profile.d/下的可以重新登录或者执行source /etc/profile还有一个更粗暴但有效的办法——直接重启终端窗口或者远程 SSH 断开重连。我个人强烈建议在配置完之后重新打开一个终端再测试而不是在旧终端里反复 source。因为 source 只在当前终端里生效新开终端能不能自动生效才是真正的检验标准。4.4 配置验证的标准流程配置完环境变量后不要只敲一个java -version就完了要做一套完整的验证流程确认各个层面都正常java -version javac -version echo $JAVA_HOME which java我来解释为什么要逐个看java -version验证运行时能不能用报错command not found说明 PATH 没配上javac -version验证编译器没有这个说明你装的是 JRE 而不是 JDKecho $JAVA_HOME确认变量本身有没有值空输出说明 export 语句没加载which java查看实际调用的二进制路径这一步能帮你发现有没有被其他位置的 JDK 抢占。如果你想让别人也能验证你配的环境用ls -l $(which java)它能展示符号链接的解析链一眼就能看清楚java命令最终指向哪里多版本切换的时候特别有用。5. 多版本 JDK 共存与切换这招学会了终身受用5.1 场景老项目 JDK 8新项目 JDK 17怎么在一台机器上共存你在公司维护着一个老系统跑在 JDK 8 上不能动同时又在开发一个新项目要用 JDK 17。如果只配一个JAVA_HOME两个项目总有一个要罢工。最朴素也是很多人用过的最土的办法每次切换项目就改环境变量然后source ~/.bashrc新旧终端来回折腾。这个方法能用但效率低到令人发指。更好的办法是利用 update-alternatives 工具。这是 Debian/Ubuntu 系内置的工具专门用来管理系统里同种命令的符号链接。CentOS 系也有类似的机制alternatives命令。先把你安装的多个 JDK 都注册进去sudo update-alternatives --install /usr/bin/java java /usr/local/java/jdk-8/bin/java 1 sudo update-alternatives --install /usr/bin/java java /usr/local/java/jdk-17/bin/java 2 sudo update-alternatives --install /usr/bin/javac javac /usr/local/java/jdk-8/bin/javac 1 sudo update-alternatives --install /usr/bin/javac javac /usr/local/java/jdk-17/bin/javac 2然后随时切换sudo update-alternatives --config java它会列出一个交互式菜单让你输入数字选择当前环境用哪个版本。这个操作立刻生效不需要重启终端。但注意update-alternatives管理的是java、javac这些命令的指向它并不会自动更新JAVA_HOME变量。所以如果你的工具比如 Maven依赖JAVA_HOME你还得配合脚本动态设置。5.2 自定义切换脚本一条命令完成切换我个人常用的做法是写一个简单的 shell 函数放到~/.bashrc里function setjdk() { if [ -z $1 ]; then echo 用法: setjdk 8 或 setjdk 17 return fi export JAVA_HOME/usr/local/java/jdk-$1 export PATH$JAVA_HOME/bin:$PATH java -version }然后我只需要在终端里执行setjdk 17就能立刻切换到 JDK 17。这个函数唯一的硬性要求是你的 JDK 目录名必须带版本号比如/usr/local/java/jdk-8和/usr/local/java/jdk-17。配合前面说的软链接方案目录名一统一管理起来非常清爽。5.3 一个容易混淆的坑JAVA_HOME 不改其他工具还是会用旧版本很多时候你发现java -version已经是新版了但 Maven 编译还是按旧版本走。原因很简单——Maven 这类工具读取的是JAVA_HOME环境变量而不是PATH里的java命令。所以每次切换JAVA_HOME和PATH要一起改。上面的setjdk函数已经帮你处理了这件事。如果你手动配置一定要记住这个逻辑别只改一个。6. 常见问题与排查技巧实录6.1 问题速查表报错信息可能原因解决思路bash: java: command not foundPATH没配置或没生效检查export PATH是否写入正确文件执行source后再试java -version显示旧版本有其他 JDK 抢占了PATH优先级用which java看实际路径调整PATH顺序javac: command not found装的是 JRE 不是 JDK在 Ubuntu 装openjdk-17-jdkCentOS 装带-devel的包Failed to find Java VMJAVA_HOME指向了错误的路径检查JAVA_HOME是否指向包含bin/的 JDK 根目录而不是bin/本身Error: could not open .../lib/amd64/jvm.cfgJDK 目录被移动或删除但符号链接还指向旧位置检查软链接是否有效必要时重新建立Permission denied解压后的文件没有执行权限用chmod -R x /usr/local/java/jdk-17/bin或设好属主bash: ./java: cannot execute binary file架构不匹配比如 x86 系统装了 arm 包重新下载匹配架构的 JDK6.2 环境变量配置失败的三大高发原因第一个是配错了文件。把export写进了/etc/sudoers、写进了 shell 脚本、写进了/etc/profile但当前 shell 是 bash 而系统默认 shell 是 zsh——都可能造成不生效。先搞清楚你用的到底是 bash 还是 zsh配置写到对应的 rc 文件里才管用。第二个是路径多写了一层。JAVA_HOME应该指向 JDK 的根目录也就是里面有bin/和lib/的那个目录。有人图省事直接写成了/usr/local/java/jdk-17/bin结果java命令能通过PATH找到但 Maven 和 Tomcat 全懵了。第三个是新老终端混淆。在一个旧的终端窗口里执行java -version即使配置写对了可能也不生效因为旧终端的 shell 环境是启动时就定下来的。新开一个终端再验一次能避免一半的“灵异事件”。6.3 从“找不到 JDK”到定位问题的完整排查示范我拿一个真实案例演示一下排查思路。某次我在 openEuler 系统上装完 JDK执行java -version提示command not found。第一步确认 JDK 目录内容对不对ls /usr/local/java/看到目录里有jdk-17.0.127再进去看bin/java是否存在。如果文件存在说明安装包没问题问题出在环境变量上。第二步检查~/.bashrc里的配置grep JAVA_HOME ~/.bashrc如果输出为空说明当时根本没写进去。如果输出正常就用echo $JAVA_HOME看当前环境变量是多少。如果输出空说明文件没被加载如果正常显示了路径那就再往下查PATHecho $PATH看里面有没有/usr/local/java/jdk-17/bin。如果没有就说明export PATH$JAVA_HOME/bin:$PATH这一行没被执行。一步步走过去问题永远定位在某一个环节而不是靠猜。7. 一条龙总结从零到生产可用的完整命令序列为了方便大家直接抄作业我把最常用的一套流程整理在这里。以 Ubuntu 系、OpenJDK 17、tar.gz 方式为例# 1. 查看系统信息 cat /etc/os-release uname -m # 2. 下载 JDK 17以清华 Adoptium 镜像为例版本号需自行确认 cd /tmp wget https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.12_7.tar.gz # 3. 解压到目标目录 sudo mkdir -p /usr/local/java sudo tar -zxvf OpenJDK17U-jdk_x64_linux_hotspot_17.0.12_7.tar.gz -C /usr/local/java/ # 4. 建立软链接方便后续版本替换 cd /usr/local/java sudo ln -s jdk-17.0.127 jdk-17 # 5. 配置环境变量 echo export JAVA_HOME/usr/local/java/jdk-17 ~/.bashrc echo export PATH$JAVA_HOME/bin:$PATH ~/.bashrc source ~/.bashrc # 6. 验证安装 echo $JAVA_HOME java -version javac -version which java这套流程跑完你的 JDK 就是生产可用的状态了。CentOS/RHEL 系的差异主要在第 2 步的镜像路径可能要用.rpm包或不同的文件名其他逻辑完全一致。在实际操作中我还有几个小经验和大家分享。一个是安装之前先看磁盘空间JDK 除掉基础包一般占 200~300MB空间不够时解压到一半报错特别尴尬。另一个是不要用 root 用户去跑 Java 应用如果公司没有特殊要求生产环境给应用单独建一个用户是更稳妥的做法权限控制上会从容很多。再一个就是养成记录环境信息的习惯装完就写个 README 记一下 JDK 版本、安装路径、配置了哪个文件三个月后回来看你会感谢自己当时多花的那一分钟。最后再分享一个我个人的习惯每次装完 JDK我都会顺手把JAVA_HOME的值写进项目的启动脚本里而不是只依赖系统环境变量。这样即使机器上的环境变了项目本身也能通过读配置文件找到正确的 JDK。这种“双保险”思路在部署多套环境的时候尤其管用因为服务器上的全局配置总有被别的同事改动的时候而项目自己的启动脚本只归你管。不管是给客户部署还是自己上线这个习惯少踩很多雷。
返回列表