简介:面向 Linux 64 位系统的 Java 开发工具包十七长期支持版本安装包,专供 Java 开发者在 Linux 环境中搭建编译、运行与调试环境。压缩包共三百八十三个文件,体积一百七十二点一九兆字节,内含七十一份模块文件、三十八个动态链接库、大量许可证与版权文档,以及 Java 编译器、归档工具、文档生成器、交互式命令行、模块链接器等标准工具,可满足企业级应用部署与日常开发需求。已有一千六百八十人学习或下载。配套的完整工具包目录结构清晰,包含模块描述、安全策略、配置文件、命令手册页等,便于配置环境变量和深入理解 JDK 组成。安装后即可体验密封类、记录、开关表达式、文本块、模式匹配等新特性,适合需要稳定长期支持版本进行项目开发或学习最新语法的中高级开发者。
1. 别再纠结下载哪个JDK:一份tar.gz解决Linux x64上的安装与配置
很多人拿到Linux环境第一件事就是装JDK,但用发行版自带源装的版本经常不对——要么是开源版11,要么被系统旧版本占着,要么版本号不全。我一般直接下tar.gz包手动部署,尤其JDK 17这个长期支持版本,用官方提供的jdk-17_linux-x64_bin.tar.gz解压就能跑,前后不超过三分钟。这份资源就是解决Linux x64上安装JDK 17的完整流程:从下载校验、环境变量配置、多版本切换,到五个常见坑的排查实录。适合刚接触Linux的开发者,也适合被系统自带JDK折磨的运维。看完你不仅能装上JDK 17,还能顺手处理掉一半的JAVA_HOME玄学。
2. 选型与校验:JDK 17 LTS凭什么成为默认版本
2.1 开源版与系统源版本:选错JDK发行版会踩的坑
JDK 17是自2018年JDK 11之后又一个长期支持版本,而JDK 16本身不是LTS,生命周期已经结束。如果你还在用JDK 16,尤其要注意它已经无法获得免费安全更新。所以现在装新机器,直接选JDK 17是大多数人的共识。它能免费商用、包含密封类和强封装JDK内部API等特性,G1GC和ZGC在这些版本里也稳定多了。
但问题不在于JDK 17本身,而在于你从哪拿这个包。发行版自带的软件源里往往只有某个特定版本,比如开源版11,而且升级策略由系统维护者决定,你很难自定义。tar.gz包则不同,它是官方构建的二进制release,解压即用,和系统包管理器完全解耦。这意味着你可以自由决定JDK目录放哪、用哪个版本、怎么在多个版本间切换,也不会因为系统升级被强制替换。
我的经验是:除非你的项目严格依赖发行版预装的运行环境,否则一律用tar.gz手动部署。它的可移植性极强,同一份包拷贝到另一台相同架构的机器上也能用。这里有一个比较直观的差异:系统源安装会帮你管理依赖,但也会悄悄升级;tar.gz则是把整个JDK装进一个目录,删除时直接删目录加清理软链接,不会有残留依赖。
当然,tar.gz不能完全忽略系统环境。JDK 17的最低glibc要求是2.12,现代Linux基本都满足。但为了保险,下载前我会先花十秒确认系统架构和glibc版本,避免下错包。
2.2 下载前确认:架构、glibc、磁盘空间一个都不能少
在下载jdk-17_linux-x64_bin.tar.gz之前,先确认目标机器真的是x86_64架构。虽然命令只有一条,但经常有在ARM服务器上下载x64包然后一脸懵的情况。我一般用下面一组命令做环境体检:
# 确认CPU架构,x86_64就是64位,对应x64包 uname -m # 查看操作系统基本信息,判断发行版类型 cat /etc/os-release # 查看glibc版本,JDK 17要求不低于2.12 ldd --version | head -1 # 检查目标目录剩余空间,JDK 17解压后约280MB df -h /opt这四条命令分别解决四个问题。uname -m 输出x86_64才匹配文件名里的x64,如果是aarch64就需要下载对应ARM版本。cat /etc/os-release 用来判断是RPM系还是DEB系,这会影响后面清理旧JDK的方式,但不影响tar.gz安装。ldd --version 能显示glibc版本,太老的系统装JDK 17会报GLIBC版本不支持,这种情况建议先用系统源升级基础库。df -h 至少留500M空闲,因为解压过程中还有临时占位。
如果系统里已经有旧JDK,也别急着删。记录当前java路径和版本,后续第4章会告诉你怎么优雅共处。这里提一句,JDK 16的tar包其实也是x64,但它不是LTS,装完过一年又要折腾升级,所以新环境直接上17,旧项目需要16的可以走多版本共存方案。
2.3 sha256sum校验:一半的安装事故源于不校验
下载tar.gz是第一个高风险点。网络中断、镜像源污染、文件被篡改,任何一个都会让安装过程变得莫名其妙。我吃过一次亏:下载的JDK包解压后一运行就报错“Error: could not find libjava.so”,后来才发现文件本身被截断了。从那以后,每次下载完第一件事就是校验SHA256。
# 用wget下载,也可以换成curl -O wget https://download.example.com/jdk-17_linux-x64_bin.tar.gz # 计算下载文件的SHA256哈希,输出一个64位字符串 sha256sum jdk-17_linux-x64_bin.tar.gz # 从官方页面复制官方公布的SHA256值,粘贴到下面命令中比对 echo "官方发布的64位校验哈希值 jdk-17_linux-x64_bin.tar.gz" | sha256sum -c -sha256sum -c - 的意思是从标准输入读取“期望哈希值+空格+文件名”的格式,然后自动校验。注意“官方发布的64位校验哈希值”需要替换成官网给出的真实字符串,且文件名必须和你实际下载的文件名一致。如果输出“OK”就说明文件完整,输出“FAILED”则文件有问题,必须重新下载。顺便说下,md5已经不适合用于安全校验,优先用sha256或更高。
2.4 备份旧JDK:卸载前先留后悔药
如果你机器上已经有其他JDK,先别急着删。记录当前版本:java -version,再查路径:which java和readlink -f $(which java)。我习惯把旧JDK目录改名而不是直接删除,比如mv /opt/jdk-11 /opt/jdk-11.bak。这样新JDK万一出了诡异问题,改回名字就能立刻回滚。这个操作花不了十秒钟,但能帮你避免一次通宵排障。
3. 安装与配置:从解压到java -version只需六步
3.1 解压到/opt/java/jdk-17:目录规划决定后期维护体验
tar.gz包的解压非常简单,但目录规划是有讲究的。很多人直接解压到/home/用户或/usr/local,等后面配环境变量时才发现路径乱七八糟。我统一使用/opt/java作为JDK家族的家,每个版本一个子目录,再加一个无版本号的软链接指向当前默认版本,这样以后升级只需要改一个软链接。
# 解压tar.gz,通常解开出jdk-17.x.y这样的目录 tar -zxvf jdk-17_linux-x64_bin.tar.gz # 创建统一目录,并移动解压出来的文件夹 sudo mkdir -p /opt/java sudo mv jdk-17.* /opt/java/jdk-17 # 创建无版本号的软链接,后面所有配置都使用这个链接 sudo ln -s /opt/java/jdk-17 /opt/java/current解压后的目录名里包含具体补丁版本号,比如jdk-17.0.9,保留它方便精确管理。ln -s建立/opt/java/current软链接,指向当前正在使用的JDK目录。之后配置环境变量时全部引用/opt/java/current,而不是写死某个带版本号的路径。这样以后从17.0.5升到17.0.9,只需要改软链接指向,所有配置都不用动。
3.2 配置JAVA_HOME与PATH:全局与用户级怎么选
接下来是核心配置。JAVA_HOME指向/opt/java/current,PATH则把$JAVA_HOME/bin放在最前面,确保系统优先找到我们刚装的JDK。这里有个关键点:设置全局环境变量时,放在/etc/profile.d/java.sh里比直接改/etc/profile更干净,因为这个目录下的脚本会被登录shell自动加载,而且单独隔离出一个文件方便管理。
# 创建环境变量配置文件 sudo vi /etc/profile.d/java.sh写入以下内容:
# JAVA_HOME指向软链接,而不是具体版本目录 export JAVA_HOME=/opt/java/current # PATH一定要把$JAVA_HOME/bin放在最前面 export PATH=$JAVA_HOME/bin:$PATH保存后,让当前会话立即加载:
source /etc/profile.d/java.sh如果你只想给当前用户配置,则改~/.bashrc,内容一样。区别在于/etc/profile.d对所有用户生效,适合服务器;~/.bashrc只对当前用户生效,适合个人开发机。注意,很多新手的错误是PATH里写成了export PATH=$PATH:$JAVA_HOME/bin,把系统路径放在前面,这样系统自带的旧JDK会优先被找到,导致java版本不对。所以顺序很重要。
3.3 编译HelloWorld验证编译器正常
安装完成后的验证不能只看java -version,因为有些环境只配了运行时,javac命令却找不到。我给了一个三步验证法:查运行时版本、查编译器版本、编译运行一个真实的小程序。
# 验证Java运行时版本 java -version # 验证Java编译器版本 javac -version # 写一个最简单的Java程序 cat > Hello.java <<'EOF' public class Hello { public static void main(String[] args) { System.out.println("JDK 17 OK"); } } EOF # 编译并运行 javac Hello.java java Hello如果java -version输出的版本号不是17开头,说明PATH配置有问题,需要回到上一节检查。如果javac命令找不到,说明JAVA_HOME没生效或者PATH没把bin目录包含进去。如果编译运行一切正常,输出“JDK 17 OK”,说明安装完全成功。这一套验证做了之后,基本可以放心使用,不会出现运行时和编译器不一致的情况。
4. 多版本共存:用update-alternatives解决JDK 17与旧版打架的问题
4.1 系统自带JDK冲突:先查rpm -qa和which java
服务器上经常预装了旧JDK,或者开发机同时存在JDK 8、11、17多个项目需求。装完JDK 17后,执行java -version却显示旧版本,这是最典型的冲突场景。原因很简单:/usr/bin/java软链接还指向系统自带的JDK,而我们配置的PATH优先级可能没有覆盖它。先通过两条命令定位问题根源。
# 查看当前java命令实际解析到哪个目录 which java ls -l /usr/bin/java # 排查基于RPM的系统上安装的JDK包 rpm -qa | grep -E 'java|jre'which java会显示当前PATH中第一个java的位置,比如/usr/bin/java。ls -l可以看到软链接的真实指向。如果它指向例如/etc/alternatives/java,那么你的系统已经接管了java命令。rpm -qa列出的包名类似java-11-openjdk-*,找到后你可以决定是卸载还是保留。我的建议是:不要急着卸载系统JDK,而是用update-alternatives把JDK 17注册进去,让工具帮我们管理优先级。
4.2 注册update-alternatives:不同版本随意切换
update-alternatives是Linux上管理软链接的标准工具,它能把多个版本的同一命令注册成可选候选,用户通过一条命令切换。我们先把JDK 17的java和javac都注册进去。
# 安装JDK 17的java命令,优先级设为100 sudo update-alternatives --install /usr/bin/java java /opt/java/current/bin/java 100 # 安装JDK 17的javac命令,优先级设为100 sudo update-alternatives --install /usr/bin/javac javac /opt/java/current/bin/javac 100 # 列出当前已注册的所有java版本 sudo update-alternatives --list java # 进入交互式切换菜单,输入对应数字选择版本 sudo update-alternatives --config java注册命令中的/usr/bin/java是最终软链接的路径,java是链接组名,/opt/java/current/bin/java是候选的真实路径,100是优先级——数字越大,系统默认情况下越优先选中。执行--config java后,会列出所有已注册的java版本,你会看到之前系统自带的旧JDK和自己的JDK 17,输入数字回车即可切换。
4.3 排查PATH优先级:which -a java告诉你真相
即使设置了update-alternatives,有时shell还是会找错版本,因为PATH里存在多个java。我习惯用which -a java查看PATH中所有可用的java位置,按顺序显示。
# 输出当前PATH环境变量 echo $PATH # 列出所有位于PATH中的java可执行文件 which -a java # 查看一个命令最终被解析到哪一个路径 type -a javawhich -a java会输出类似/opt/java/current/bin/java和/usr/bin/java这样的多行结果,从上到下就是PATH查找顺序。如果发现/usr/bin/java排在前面,说明/etc/profile.d/java.sh里的PATH配置顺序错了。另外注意,sudo执行命令时不会保留用户环境变量,所以sudo java -version可能显示旧版本,这不代表配置失败,可以sudo env "PATH=$PATH" java -version验证。
5. 避坑指南:五条常见安装事故与排查实录
5.1 现象:java -version显示旧版本号
刚装完JDK 17,执行java -version输出的却是1.8或11。原因主要有两个:PATH中$JAVA_HOME/bin没有排在首位,或者系统/usr/bin/java被update-alternatives优先级更高的旧版本占据。解决方法是先检查/etc/profile.d/java.sh里PATH写法,确保是export PATH=$JAVA_HOME/bin:$PATH;再用update-alternatives --config java手动选择JDK 17。如果重启终端后发现又变回去,检查是否在~/.bashrc里二次覆盖了PATH。
5.2 现象:解压时提示Cannot open或No space left on device
tar -zxvf过程中报错无法打开文件,或者提示磁盘空间不足。可能原因包括:下载的tar.gz包不完整,解压出来文件损坏;/opt分区没有足够空间。处理办法:先sha256sum校验文件,确认哈希一致;再用df -h /opt看剩余空间。另外一个隐藏坑是文件系统类型,在vfat或ntfs挂载盘上解压会丢失符号链接和权限位,导致后续无法执行。所以解压和目标位置必须在Linux原生文件系统(如ext4)上。
5.3 现象:环境变量写对了但新开终端不生效
修改/etc/profile.d/java.sh后,当前shell执行source生效,但一开新终端又失效。原因在于你登录用的shell可能是zsh而不是bash,它不自动加载/etc/profile.d下的脚本。解决方式是检查echo $SHELL,如果是zsh,把export JAVA_HOME=...和export PATH=...写入~/.zshrc;或者把配置写入/etc/zshenv。对于SSH连接,非交互式shell也不会加载profile,这时可以在~/.ssh/environment里配置,或者统一使用update-alternatives直接改/usr/bin/java,不依赖环境变量。
5.4 现象:/usr/bin/java软链接失效
手动创建/usr/bin/java软链接指向某个JDK目录,后来该目录路径变了或移动了,软链接就断掉,执行java报实找不到。还有的情况是update-alternatives没注册完整,只注册了java没注册javac。解决方法是:不要手动维护软链接,而是坚持用update-alternatives --install注册;如果已经失效,先删掉旧链接sudo rm -f /usr/bin/java,再重新注册JDK 17的java和javac。另外,软链接目标是/opt/java/current/bin/java时,要确保/opt/java/current本身存在且指向正确目录。
5.5 现象:JVM启动报错Invalid initial heap size
程序启动时JVM直接崩溃,报Invalid initial heap size -Xms4096m。这通常是全局环境变量里设置了过大的Java堆内存参数,比如在/etc/profile或JAVA_TOOL_OPTIONS里写死了-Xms4096m,而机器物理内存不足。解决方法是逐一排查:echo $JAVA_TOOL_OPTIONS、grep -r Xms /etc/profile.d/,找到后注释或修改。JDK 17的默认堆是物理内存的1/4,一般不用手动设初始堆大小,真要调优也要先看机器内存再决定。
6. 进阶验证:压测JDK 17启动性能与JVM参数调优
6.1 用jcmd与PrintFlagsFinal验证核心库
安装完成后,常规验证只能说明能跑HelloWorld,但JVM是否健康需要更深入的确认。JDK 17自带一系列工具链,在bin目录下可以找到jcmd、jhsdb、jfr等。我最常用的一个是java -XX:+PrintFlagsFinal -version,它会把所有JVM参数的最终值打印出来,包括GC类型、最大堆、是否开启JFR等。输出几百行是正常的,重点看开头部分有没有“Error”或“Unrecognized”字样。再用jcmd -l列出当前正在运行的JVM进程,如果没有报错,说明安装没有问题。
6.2 一个脚本完成多版本JDK自动切换
日常开发中,我经常要在JDK 11和JDK 17之间切换。手动改软链接太慢,我写了一个小脚本,放在/usr/local/bin下,配合/opt/java/current软链接一起用。
#!/bin/bash # 定义已安装的JDK目录 JAVA_11=/opt/java/jdk-11 JAVA_17=/opt/java/jdk-17 if [ "$1" = "11" ]; then sudo ln -sfn $JAVA_11 /opt/java/current elif [ "$1" = "17" ]; then sudo ln -sfn $JAVA_17 /opt/java/current else echo "Usage: switch-java [11|17]" exit 1 fi # 重设当前会话的环境变量 export JAVA_HOME=/opt/java/current export PATH=$JAVA_HOME/bin:$PATH # 立即验证 java -version脚本的关键是sudo ln -sfn:-s表示软链接,-f表示强制覆盖已有链接,-n把/opt/java/current当作普通文件处理,防止在目录下创建子链接。因为全局配置已经让所有终端用$JAVA_HOME/bin,所以切换软链接后,新开终端自然使用目标版本。我还加入了一个习惯:每次切换后强制java -version确认输出,避免脚本路径写错留着黑匣子。
从那以后我每次装JDK都强制走一遍“下载校验→记录旧版→解压到独立目录→建current软链接→配profile→注册alternatives→运行HelloWorld”的完整流程,再也没碰过“java命令找不到”之类的玄学问题。希望帮到你。
本文还有配套的精品资源,点击获取