简介:面向Linux运维与后端开发者的JDK 8u321 AArch64平台部署资源,专为ARM64架构服务器场景准备,解决Java运行环境在64位ARM服务器上的安装配置与稳定运行问题,适合需要搭建分布式服务、微服务节点或Hadoop集群的中高级运维人员。压缩包共406个文件,约71.02MB,以可执行程序、so动态库、jar包、properties配置、md文档及ttf字体等为主,涵盖编译器、运行环境与jstat、jmap、jstack等诊断工具,目录结构完整还原JDK发行版布局。已有1676人学习下载。资源包含解压即用的完整JDK目录,配合环境变量配置即可完成部署,并附有JVM性能监控、参数调优与内存溢出排查思路,便于读者快速在AArch64服务器上验证java -version并投入生产使用。
1. 从一台 ARM 服务器上装不上 JDK 说起
上周给一台 ARM 架构的服务器装 JDK,随手敲了yum install java-1.8.0-openjdk,装完java -version一看是 1.8.0_262,跟业务方要求的 8u321 对不上,换alternatives切了半天也没用,最后发现仓库里压根没有这个版本。这种翻车在 ARM 机器上特别常见:x86 上闭着眼apt或yum就能搞定的事,到了 aarch64 上,发行版仓库给的包要么版本老,要么干脆没有,只能老老实实下jdk-8u321-linux-aarch64.tar.gz这种官方二进制包手动铺。这篇笔记就是把这套流程从头到尾走一遍——版本怎么选、包怎么下、目录怎么放、环境变量怎么写、装完怎么验证、装坏了怎么回滚,适合正在 ARM 服务器上折腾 Java 运行环境、被版本和架构卡住的 Linux 运维和分布式后端开发者。
2. 装前把环境盘清楚:架构、发行版和版本三件事
动手之前先把三件事确认掉,能省掉后面一大半返工。很多人拿到一个 tar.gz 就急着解压,结果解压完发现架构不对、glibc 太老、或者跟机器上已有的 JDK 打架,这些坑其实在装之前就能排掉。
2.1 先确认 CPU 架构,别把 aarch64 包装到 x86 上
jdk-8u321-linux-aarch64.tar.gz这个文件名里,aarch64就是架构标识,它只能跑在 64 位 ARM 上。x86_64 的机器要装的是jdk-8u321-linux-x64.tar.gz,两个包互不通用,装错了执行java会直接报cannot execute binary file。确认命令很简单:
# 查看内核架构,aarch64 或 arm64 才是 ARM 64 位 uname -m # 再看一眼 CPU 信息,确认是 ARM 平台 lscpu | grep -i "architecture\|model name"uname -m输出aarch64就对了;如果输出x86_64,说明你下错包了,回去换 x64 版本。有些发行版uname -m会显示arm64,这也是 ARM 64 位,跟aarch64是同一个东西,不用慌。我一般还会顺手看一眼getconf LONG_BIT,确认是 64 位系统,32 位系统装不了这个包。
2.2 发行版和 glibc 版本,决定这个包能不能跑
Oracle 官方给的 8u321 二进制包对 glibc 有最低要求,太老的系统(比如 CentOS 6 那一代)跑起来会报GLIBC_2.14 not found之类的错。装之前查一下:
# 查看发行版版本 cat /etc/os-release # 查看 glibc 版本 ldd --version | head -n 1CentOS 7 / Ubuntu 16.04 及以上的 glibc 一般都够用,CentOS 6 这种就得掂量一下了。另外 ARM 平台上还要注意一点:部分精简版镜像裁掉了libX11、libXext这类图形库,虽然跑服务端 Java 用不上图形界面,但 JDK 里有些工具(比如jconsole)会依赖它们,启动时报libX11.so.6: cannot open shared object file。纯跑服务的话可以不管,要用监控工具就补装一下libX11和libXext。
2.3 版本选择:为什么是 8u321 而不是更新的 8u3xx
JDK 8 的更新版本号一路涨到 8u4xx,但生产上不是越新越好。8u321 属于 8u311 之后的稳定更新,修了一批安全漏洞,同时没有引入大的行为变化,很多中间件和框架的兼容性矩阵里都把它列为推荐版本。选版本时我一般看三个点:业务方或中间件文档里写没写死版本、机器上现有 JDK 是什么版本(避免同一台机器上版本跨度太大)、以及这个版本有没有已知的严重回归。如果业务方明确要求 8u321,那就别自作主张升到 8u401,版本对齐比追新重要得多。
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| CPU 架构 | uname -m | aarch64 / arm64 |
| 系统位数 | getconf LONG_BIT | 64 |
| 发行版 | cat /etc/os-release | CentOS 7+ / Ubuntu 16.04+ |
| glibc 版本 | ldd --version | 2.17 及以上 |
| 已有 JDK | which java && java -version | 记录现有版本和路径 |
这张表建议装之前逐行过一遍,尤其是「已有 JDK」这一行——很多机器上预装了 OpenJDK,装完新 JDK 后java -version还是老版本,就是因为 PATH 或alternatives没处理干净,后面第 5 章会专门讲。
3. 下载与解压:目录规划和解压参数
环境确认完,进入实际安装。这一步看着简单,但目录放哪、权限怎么给、解压用什么参数,都会影响后面环境变量和运维习惯。
3.1 下载包并校验完整性
包从官方渠道拿,拿到后先校验,别嫌麻烦。传输中断导致的半截包解压时不一定报错,但跑起来各种诡异问题,这种玄学问题排查起来最费时间。
# 下载(示例路径,按实际存放位置调整) cd /opt/soft # 校验文件大小和类型,确认是 gzip 压缩的 tar 包 file jdk-8u321-linux-aarch64.tar.gz ls -lh jdk-8u321-linux-aarch64.tar.gz # 如果有官方提供的校验值,比对一下 sha256sum jdk-8u321-linux-aarch64.tar.gzfile命令输出里应该能看到gzip compressed data,如果显示ASCII text或者HTML document,说明下下来的是个错误页面,重新下。sha256sum的结果跟官方公布的值对不上就别用,宁可重下也别赌。
3.2 解压到 /usr/local,别放 /opt 或家目录
目录规划这块,我踩过的坑是早期图省事解压到/root下,后来换人维护、家目录被清理,JDK 跟着没了,服务全挂。现在统一放/usr/local/,这是放第三方软件的惯例位置,权限清晰,也不会被系统清理策略误伤。
# 解压到 /usr/local tar -zxvf jdk-8u321-linux-aarch64.tar.gz -C /usr/local/ # 确认解压出来的目录名 ls -ld /usr/local/jdk1.8.0_321-z表示 gzip 解压,-x是解包,-v显示过程,-f指定文件名,-C指定目标目录。解压出来的目录名一般是jdk1.8.0_321,这个目录名后面写环境变量要用到,别记错。如果想让路径更短、更好记,可以建个软链接:
# 建软链接,方便后续升级时只改链接指向 ln -s /usr/local/jdk1.8.0_321 /usr/local/java用软链接的好处是以后升级 JDK 只改链接指向,环境变量里写/usr/local/java就不用动。这个习惯在需要频繁切版本的机器上特别值。
3.3 权限设置:别让普通用户跑不起来
解压出来的文件默认属主是执行解压的用户,如果当时用的是 root,普通业务用户可能没有执行权限。给一个合理的权限:
# 目录属主给 root,组给一个业务组,权限 755 chown -R root:root /usr/local/jdk1.8.0_321 chmod -R 755 /usr/local/jdk1.8.0_321 # 验证 bin 下的 java 有执行权限 ls -l /usr/local/jdk1.8.0_321/bin/java755意味着属主可读写执行、组和其他用户可读可执行,对 JDK 这种只需要读和执行的目录足够。不建议图省事chmod -R 777,生产环境上这是给自己埋雷。如果业务以非 root 用户运行,确认该用户对/usr/local/jdk1.8.0_321有读和执行权限即可,不需要写权限。
4. 配置环境变量:JAVA_HOME 和 PATH 的写法与取舍
环境变量配错是 JDK 装完后最常见的问题来源,java -version显示老版本、JAVA_HOME为空导致 Tomcat 起不来、脚本里$JAVA_HOME/bin/java找不到,基本都是这一节的事。
4.1 全局配置写在 /etc/profile.d 下
环境变量有几种写法:改/etc/profile、改~/.bashrc、或者在/etc/profile.d/下放一个独立脚本。我一般选第三种,好处是配置独立成文件、好找好删、不会把系统自带的 profile 改乱。
# 新建独立的环境变量脚本 cat > /etc/profile.d/jdk.sh <<'EOF' # JDK 8u321 环境变量 export JAVA_HOME=/usr/local/java export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:${PATH} EOF # 给脚本加执行权限并立即生效 chmod +x /etc/profile.d/jdk.sh source /etc/profile.d/jdk.sh逐行说明一下:JAVA_HOME指向 JDK 根目录,这里用软链接/usr/local/java,升级时只改链接;JRE_HOME指向 JDK 内置的 jre 目录,JDK 8 里 jre 是包含在 JDK 目录下的;CLASSPATH里的.表示当前目录,后面两个是 JDK 自带的类库路径,虽然现在很多应用不依赖全局 CLASSPATH,但一些老脚本会读它,留着更稳;PATH把 JDK 的 bin 目录放到最前面,保证java、javac优先命中新装的这个。
提示:
/etc/profile.d/下的脚本只对登录 shell 生效。如果服务是通过 systemd 或非登录 shell 启动的,环境变量可能读不到,这种情况要在服务单元文件里显式写Environment=JAVA_HOME=/usr/local/java,或者用绝对路径调用 java。
4.2 用户级配置和全局配置的取舍
如果机器上多个业务用户需要不同 JDK 版本,就别动全局配置,改到各自家目录的~/.bashrc里:
# 追加到当前用户的 ~/.bashrc echo 'export JAVA_HOME=/usr/local/java' >> ~/.bashrc echo 'export PATH=${JAVA_HOME}/bin:${PATH}' >> ~/.bashrc source ~/.bashrc全局配置适合整机统一版本的情况,用户级配置适合多版本共存。两者同时存在时,用户级配置后加载会覆盖全局的,容易造成「同一个命令不同用户看到不同版本」的困惑,所以要么统一走全局,要么明确约定用户级优先,别混着来。
4.3 和系统自带 OpenJDK 的冲突处理
很多发行版预装了 OpenJDK,/usr/bin/java是个软链接,指向alternatives管理的版本。装完新 JDK 后如果java -version还是老版本,先看which java指向哪:
# 查看 java 实际指向 which java ls -l $(which java) # 如果系统用 alternatives 管理,注册新版本 alternatives --install /usr/bin/java java /usr/local/java/bin/java 200 alternatives --config java--install的最后一个数字是优先级,数字越大越优先,这里给 200 保证新装的版本排在前面。--config会列出所有已注册的 java,手动选一下。如果系统没用 alternatives,那就靠 PATH 顺序解决,确认/etc/profile.d/jdk.sh里的 PATH 把 JDK bin 放最前面即可。
5. 避坑与排查:装完跑不起来的五种典型情况
这一节按「现象 → 原因 → 解决」整理,都是我在 ARM 机器上装 JDK 8 时真实遇到过的,按出现频率从高到低排。
5.1 现象:java -version显示的还是老版本
原因:PATH 里系统自带的 java 路径排在前面,或者当前 shell 没重新加载环境变量。解决:先echo $PATH看 JDK bin 在不在最前,不在就source /etc/profile.d/jdk.sh;如果 PATH 对了但版本还不对,用which -a java列出所有 java,确认实际执行的是哪个,再按 4.3 节处理 alternatives 或软链接。
5.2 现象:执行 java 报cannot execute binary file
原因:架构不匹配,把 x64 的包装到了 ARM 机器上,或者反过来。解决:uname -m确认架构,重新下载对应架构的包。这个错误不会骗人,看到就直接换包,别在权限和依赖上浪费时间。
5.3 现象:启动时报GLIBC_2.14 not found或类似版本错误
原因:系统 glibc 版本低于 JDK 要求。解决:ldd --version确认版本,CentOS 6 这类老系统要么升级系统,要么换一个对 glibc 要求更低的 JDK 构建版本。硬升 glibc 风险很高,容易把系统搞坏,不推荐在生产机上干。
5.4 现象:JAVA_HOME明明配了,Tomcat 或脚本还是报找不到
原因:服务不是通过登录 shell 启动的,没读到/etc/profile.d/下的配置。解决:在启动脚本里显式export JAVA_HOME=/usr/local/java,或者 systemd 服务里加Environment=行。判断方法是在服务进程的环境里看:cat /proc/<pid>/environ | tr '\0' '\n' | grep JAVA_HOME,没有就是没读到。
5.5 现象:解压时报gzip: stdin: not in gzip format
原因:下载的包不完整或者是错误页面。解决:file看文件类型,ls -lh看大小是否明显偏小,重新下载并校验 sha256。这个坑在弱网环境下特别常见,下完不校验,解压报错还算好的,最怕解压成功但文件损坏,跑起来随机崩。
6. 装完怎么验证:从版本号到实际跑一个类
装完不验证等于没装。我一般分三层验证:版本层、环境变量层、实际运行层,三层都过才算这套环境真的可用。
第一层看版本和路径是否对得上:
# 版本必须是 1.8.0_321 java -version javac -version # 确认 java 来自我们装的目录 readlink -f $(which java) echo $JAVA_HOMEjava -version输出里要能看到1.8.0_321,readlink -f $(which java)的结果应该落在/usr/local/jdk1.8.0_321/bin/java上,JAVA_HOME输出/usr/local/java。三个都对,说明版本和环境变量这层没问题。
第二层验证编译和运行链路,写个最小类跑一下:
# 写一个最小测试类 cat > /tmp/HelloJdk.java <<'EOF' public class HelloJdk { public static void main(String[] args) { System.out.println("JDK: " + System.getProperty("java.version")); System.out.println("Arch: " + System.getProperty("os.arch")); } } EOF # 编译并运行 cd /tmp javac HelloJdk.java java HelloJdk输出里JDK: 1.8.0_321和Arch: aarch64都对,说明编译器和运行时都正常,架构也没问题。这一步能同时验证javac和java两个命令,比只看java -version更实在。
第三层看内存和 JVM 参数是否正常,尤其是 ARM 机器上堆内存的默认值:
# 查看 JVM 默认堆参数 java -XX:+PrintFlagsFinal -version 2>/dev/null | grep -i "MaxHeapSize\|InitialHeapSize" # 跑一个带堆参数的小测试,确认参数生效 java -Xms256m -Xmx512m -XX:+PrintFlagsFinal -version 2>/dev/null | grep -i MaxHeapSizeMaxHeapSize应该跟你传的-Xmx512m对得上(单位是字节)。ARM 服务器内存配置跟 x86 不太一样,有些云主机默认堆大小算出来偏小,业务跑起来频繁 Full GC,这时候就要在启动参数里显式指定-Xms和-Xmx,别完全依赖默认值。
| 验证层 | 命令 | 通过标准 |
|---|---|---|
| 版本层 | java -version | 显示 1.8.0_321 |
| 路径层 | readlink -f $(which java) | 指向 /usr/local/jdk1.8.0_321/bin/java |
| 编译层 | javac HelloJdk.java && java HelloJdk | 正常输出,无报错 |
| 架构层 | 测试类输出os.arch | aarch64 |
| 参数层 | -XX:+PrintFlagsFinal | 堆参数与传入值一致 |
这套验证走完,基本能确认 JDK 装好了、环境变量生效了、编译运行链路通了、架构和参数都对。从那以后我每次装完 JDK 都强制走一遍这三层验证,尤其是第二层的编译运行测试——只看java -version太容易骗过自己,真正跑一个类才知道这套环境是不是真的能用。希望帮到你。
本文还有配套的精品资源,点击获取