☰
aarch64 Linux 下 OpenJDK 11 tar.gz 部署全流程与避坑指南
2026/10/17 12:08:06 网站建设 项目流程

简介:面向 Linux aarch64(ARM 64 位)平台的 OpenJDK 11 标准发行包,版本为 11.0.10+9,适合服务器运维、嵌入式开发或需要在 ARM 设备上运行 Java 应用的开发者直接部署使用。压缩包共包含 508 个文件,整体约 182MB,主体以模块文件、动态链接库、许可证与说明文档为主,同时提供编译、运行、调试、交互式验证等完整工具链,目录结构清晰,解压后即可得到完整的 JDK 开发环境,目前已有 1240 人学习下载。OpenJDK 11 默认采用 HotSpot 虚拟机,在模块化系统基础上进一步完善,内置了标准的 HTTP 客户端接口,支持文本块、局部变量类型推断(var)等特性,并保留 JShell 便于快速验证代码片段。在 aarch64 架构下,这套环境能发挥 64 位寻址与大内存并行计算优势,省去自行编译源码或处理依赖的麻烦,配置 PATH 后即可直接使用,适合个人开发者、团队以及云上 ARM 服务器等各类 Java 应用落地场景。

1. 从 tar.gz 到可用的 JDK 11:aarch64 平台绕不开的一次解压

在 Linux aarch64 服务器上部署 openjdk11,最常见的翻车点不是配置写错,而是拿了一个 x86_64 的安装包硬跑。OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.10_9.tar.gz这颗包是专门为 ARM 64 位 Linux 预编译好的 JDK 11 完整版,解压就能用,不需要 RPM、不跑 configure。我之前做某跨平台系统迁移时,光“java: cannot execute binary file”这个报错就帮人排查过十几次,原因几乎都是平台选错。这份资源解决的就是“在 aarch64 环境里有一个能跑 Spring Boot、Spark 的 JDK”这个基础诉求,适合 ARM 云服务器、边缘网关、异构集群的开发者。下面从包名开始拆,把部署步骤、验证方法和排障细节一次讲完。

2. 先看懂包名再动手:HotSpot、aarch64 与 11.0.10_9 的命名字典

拿到文件名先别急着解压,这个命名规范本身就把平台、虚拟机实现、版本号全告诉你了。读错一个字段,后面可能白忙半小时。

2.1 文件名里的每一个字段代表什么

字段含义
OpenJDK11UJDK 11 的 Update 版本系列标识,U 表示 Update
jdk完整开发套件,包含 javac、jlink、jhsdb 等工具,不是精简版 JRE
aarch64ARM 64 位架构,对应 ARMv8-A 及以上处理器
linux目标操作系统是 Linux
hotspot虚拟机实现是 HotSpot,不是 OpenJ9、GraalVM 等替代实现
11.0.10Java 版本号,属于 JDK 11 的第 10 次更新
_9该版本的第 9 次构建编号,通常对应某个安全补丁级别

这里要特别强调aarch64和arm64的关系。日常交流里这两个词经常混用,软件源里也可能出现arm64的目录名,但在 OpenJDK 官方构建产物的命名里,aarch64是标准叫法。如果你的设备是 32 位 ARM 内核,包名会变成armv7l或armhf,把那种包装到 64 位系统上,轻则报“Exec format error”,重则启动后出现非法指令直接崩溃。

判断当前系统架构的标准命令是:

uname -m

输出aarch64说明平台匹配。如果输出armv7l,那这颗包不适用,需要去找 32 位 ARM 的 JDK。还有一个容易忽略的细节:arch命令在某些精简系统里不存在,uname -m是更通用的做法。

2.2 为什么选 HotSpot 而不是其他虚拟机实现

JDK 11 时代的虚拟机实现主要有三条路线:HotSpot、OpenJ9、GraalVM。这个包名里明确写了hotspot,说明这是上游社区默认的 HotSpot 构建,也是绝大多数 Java 应用默认依赖的运行时。

HotSpot 在 aarch64 平台的适配历史可以从 JEP 237 算起,JDK 9 开始官方支持 Linux/AArch64,到 JDK 11 时 C1 和 C2 编译器都已经有完整的 AArch64 后端。这意味着一线生产环境常见的微服务、大数据组件、中间件,基本都能在这套运行时上直接工作。相比之下,OpenJ9 虽然启动内存占用更小,但在 ARM 平台上的默认分发版本不如 HotSpot 普及,很多第三方组件做兼容性验证时也优先测 HotSpot。

还有一点是排查问题时的心态:HotSpot 的报错日志和诊断工具(jstack、jmap、jcmd)资料最多,网上搜某个异常时八成以上结果是 HotSpot 环境。在 aarch64 上如果选小众虚拟机,遇到问题常常连个对照实验都没得做。所以除非团队里有明确理由,否则默认选 HotSpot 构建是风险最低的决策。

2.3 预编译包和源码编译的取舍

aarch64 的 OpenJDK 源码编译,我劝退过不少人。它不像 x86_64 上那样 configure、make、make install 三连就完事。常见做法是要先准备一个同架构的 bootstrap JDK,再配置--openjdk-target=aarch64-linux-gnu和交叉编译工具链,期间还要处理--with-jvm-features、--with-native-debug-symbols这些参数。

我在某开发板上试过一次交叉编译,光解决libffi、freetype的依赖就花了半天,最后编出来的产物在 gc 日志上还出现诡异延迟。后来果断放弃源码编译,直接用预编译包。这颗 tar.gz 就是别人已经编译好的产物,解压后java -version能出结果,比什么都强。对于绝大多数业务场景,预编译包完全够用,没必要把时间花在重复造 JDK 上。

3. 部署与验证:把 JDK 11 装进 ARM 云服务器的完整过程

这一章直接进入实操。以/opt/java作为安装目录,从校验文件完整性到多版本切换,每一步都可以直接抄。

3.1 校验压缩包完整性

网络传输过程中 tar.gz 可能被截断或损坏,先算一下校验值:

sha256sum OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.10_9.tar.gz

拿到输出后对照你记录的正确 SHA256 值。我一般会习惯在下载完成后立刻生成一份校验文件,再跑一次自动比对:

echo "期望的sha256值 OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.10_9.tar.gz" > checksum.txt sha256sum -c checksum.txt

-c参数会逐行读取“校验值+文件名”格式的内容并做比对。返回OK说明包完整。这一步如果输出FAILED,不要继续解压,重新下载。压缩包损坏导致的 java 启动失败,报错信息往往很迷惑,容易让人误判成 glibc 或内核问题。

3.2 解压与目录规划

建议把 JDK 放到统一目录,再用版本号区分,方便以后切换或回滚:

sudo mkdir -p /opt/java sudo tar -xzf OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.10_9.tar.gz -C /opt/java ls -l /opt/java

解压后ls应该能看到一个类似jdk-11.0.10的目录。-C指定解压目标目录,避免文件散落到当前目录。这里有个细节:tar 包内的顶层目录名通常已经带版本号,不用手动再建一层子目录。如果你解压出来的目录名和你预期不一致,不要强行 mv,直接根据实际目录名配置环境变量即可。

解压完成后确认一下关键文件:

/opt/java/jdk-11.0.10/bin/java -version

这一步如果报/bin/java: No such file or directory,注意看是不是包不完整,或者架构不对导致二进制无法执行。确认能跑通后再配置环境变量。

3.3 配置环境变量

配置环境变量我推荐写在/etc/profile.d/下,而不是改/etc/profile主文件,方便后期移除:

sudo tee /etc/profile.d/jdk11.sh >/dev/null <<'EOF' export JAVA_HOME=/opt/java/jdk-11.0.10 export PATH=$JAVA_HOME/bin:$PATH EOF source /etc/profile.d/jdk11.sh

这里用tee配合 heredoc 是为了解决 sudo 下重定向权限不足的问题。JAVA_HOME指向 JDK 的根目录,不是bin目录。PATH则把$JAVA_HOME/bin放到最前面,避免系统里其他版本的 java 抢跑。

登录 shell 会读取/etc/profile.d/下的脚本。但如果你是通过 SSH 执行非登录命令,或者用 crontab 跑任务,环境变量可能没生效,后面避坑章节还会专门说。

3.4 验证版本和 javac

配置完成后验证两件事:运行时版本和编译工具:

java -version javac -version

正常输出会包含openjdk version "11.0.10"和javac 11.0.10两行信息。如果java -version正常但javac找不到,说明 PATH 里只有 JRE 的路径或者安装的是 JRE 包。这个包名带jdk,两者应该都可用。

再验证一下JAVA_HOME被正确识别:

echo $JAVA_HOME

输出应该是/opt/java/jdk-11.0.10。有些构建工具(比如 Maven、Gradle)只认JAVA_HOME,不认 PATH,这一步漏了后面构建必挂。

3.5 多版本 JDK 共存与切换

ARM 服务器上经常同时存在 JDK 8 和 JDK 11 的诉求。用update-alternatives管理比较省心:

sudo update-alternatives --install /usr/bin/java java /opt/java/jdk-11.0.10/bin/java 111 sudo update-alternatives --install /usr/bin/javac javac /opt/java/jdk-11.0.10/bin/javac 111 sudo update-alternatives --config java

111是优先级数字,越大越优先。--config会弹出交互式列表让你选默认版本,适合在多个 JDK 间手动切换。注意 javac 也要单独注册,否则只切 java 不切 javac,后面编译时用的还是旧版本,这种“版本不一致”的问题最隐蔽。

4. 避坑指南:我在 aarch64 Linux 上部署 JDK 11 踩过的几个坑

这一节把实际部署中遇到的高频问题列出来,每条都是“现象 → 原因 → 解决”的结构,可以直接当排障手册用。

4.1 现象:java -version 报 GLIBC 版本过低

./java: /lib/aarch64-linux-gnu/libc.so.6: version GLIBC_2.28 not found

原因:OpenJDK 11 的预编译包对 glibc 版本有要求,系统 libc 太老时动态链接器找不到对应符号。常见于用旧内核的嵌入式发行版或者裁剪过的 rootfs。

解决:先查系统 glibc 版本:

ldd --version

如果版本确实偏低,两个思路:一是换一个针对老系统构建的 JDK 版本(比如某些发行商提供的兼容包);二是用容器跑,容器镜像自带新 glibc,不污染宿主机。千万别试着拷贝宿主机的 libc.so.6 到 JDK 目录,那会导致系统级崩溃。

4.2 现象:HTTPS 请求抛 SSLHandshakeException

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException

原因:JDK 自带的cacerts信任库为空或者过旧,系统里安装的 CA 证书没有被 JVM 识别。ARM 设备上尤其常见,因为很多板子出厂镜像的证书管理是裁剪过的。

解决:让 JVM 使用系统证书库,或者手动导入:

sudo ln -sf /etc/ssl/certs/java/cacerts $JAVA_HOME/lib/security/cacerts

如果系统里没有cacerts,可以用 keytool 导入单个证书:

echo | openssl s_client -connect your-server:443 2>/dev/null | \ openssl x509 > /tmp/server.crt keytool -import -trustcacerts -alias your-server \ -file /tmp/server.crt -keystore $JAVA_HOME/lib/security/cacerts \ -storepass changeit -noprompt

changeit是 JDK 默认密钥库密码,生产环境记得改掉。

4.3 现象:Java 程序中文内容显示为方块

原因:系统缺少中文字体,或者 fontconfig 没配置好。AWT/Swing 组件和 PDF 导出场景特别明显,纯后端服务在生成验证码或图片时也会中招。

解决:安装基础字体包:

sudo apt-get install -y fonts-dejavu-core fontconfig

安装后建议重启 Java 进程。如果问题还出现,看fc-list输出:

fc-list :lang=zh

输出为空说明没有中文字体,需要装中文字体包或者把 Windows 字体复制到/usr/share/fonts下,再跑fc-cache -f刷新。

4.4 现象:systemd 服务里找不到 java 命令

用 systemd 管理 Spring Boot 服务时,ExecStart直接写java -jar会报“java: command not found”,即使 shell 里已经确认能跑。

原因:systemd 默认不加载/etc/profile.d/下的环境变量,服务进程继承的环境跟你 SSH 登录时完全不同。

解决:在 service 文件里显式指定路径:

[Service] Environment=JAVA_HOME=/opt/java/jdk-11.0.10 Environment=PATH=/opt/java/jdk-11.0.10/bin:/usr/bin:/bin ExecStart=/opt/java/jdk-11.0.10/bin/java -jar /opt/app/app.jar

或者用绝对路径直接启动。不建议在 ExecStart 里写sh -c 'source ...',那是给 shell 用的,不是给 systemd 用的。

4.5 现象:容器里 java 起不来,报 Exec format error

用 Docker 跑 ARM 镜像时,基础镜像架构和 JDK 包架构不匹配会出现这个报错。比如在 ARM 宿主机上拉了一个 amd64 的镜像做 base,再 COPY 进 aarch64 的 JDK,运行时就崩。

解决:拉镜像前先确认架构:

docker info --format '{{.Architecture}}'

输出是aarch64再继续。Dockerfile 里最好写清楚。

FROM --platform=linux/arm64 debian:bullseye-slim

否则 Docker 可能自动拉取 amd64 版本,导致 JDK 平台和容器平台对不上。这个问题在混合架构集群里几乎每周都能遇到一次。

5. 进阶:离线安装、精简运行时与检查习惯

部署稳定之后,可以把这套流程固化成一个可复用的内网安装方案。下面给两个实用做法。

5.1 做一键离线安装脚本

把前面的操作收敛成一个脚本,适合批量给 ARM 服务器装 JDK:

#!/bin/bash set -euo pipefail JDK_TARBALL="OpenJDK11U-jdk_aarch64_linux_hotspot_11.0.10_9.tar.gz" INSTALL_DIR="/opt/java" sudo mkdir -p "$INSTALL_DIR" sudo tar -xzf "$JDK_TARBALL" -C "$INSTALL_DIR" JDK_HOME=$(ls -d "$INSTALL_DIR"/jdk-11.0.10) sudo tee /etc/profile.d/jdk11.sh >/dev/null <<EOF export JAVA_HOME=$JDK_HOME export PATH=\$JAVA_HOME/bin:\$PATH EOF sudo update-alternatives --install /usr/bin/java java "$JDK_HOME/bin/java" 111 sudo update-alternatives --install /usr/bin/javac javac "$JDK_HOME/bin/javac" 111 java -version

set -euo pipefail是保命配置,任何一个命令失败都直接退出。\$JAVA_HOME里的反斜杠是为了防止 heredoc 展开过早。批量执行时,把安装包和脚本放到内网源,SSH 循环跑一遍就能完成。

5.2 用 jlink 做精简运行时

如果只是跑一个 Spring Boot 服务,不需要保留完整 JDK。JDK 11 自带 jlink,可以按需裁剪:

$JAVA_HOME/bin/jlink \ --module-path $JAVA_HOME/jmods \ --add-modules java.base,java.logging,java.naming,java.management,java.security.jgss \ --output /opt/jre-mini

--add-modules按模块清单裁剪,体积通常能从 300MB 压到 100MB 以内。做容器镜像时可以直接把/opt/jre-mini放进去,镜像更小,启动也更快。裁剪前建议先用jdeps --print-module-deps分析应用依赖了哪些模块,别凭感觉乱删。

5.3 我的检查习惯

那次在开发板上交叉编译翻车之后,我给自己立了一条规矩:任何一台 ARM 服务器装完 JDK,都必须跑一遍uname -m、java -version、javac -version和一次真实应用的启动测试,缺一不可。尤其是真实应用测试,只有java -version成功远不能证明环境可用,ClassNotFoundException 和 UnsatisfiedLinkError 这些坑一般要等应用跑起来才现形。从那以后我每次处理 JDK 安装问题都强制走一遍这四步验证,不再跳过。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询