news 2026/9/23 21:42:12

JDK 21 ARM64 Linux 安装与生产级部署实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JDK 21 ARM64 Linux 安装与生产级部署实践

简介:本资源是面向Linux Arm架构设备(如树莓派、国产ARM服务器等)的Java开发环境核心组件——JDK 21官方二进制发行版,专为嵌入式开发、边缘计算及国产化信创场景下的Java应用开发与部署提供完整支持。压缩包共386个文件,涵盖70个jmod模块文件(支撑JLink定制运行时)、38个so动态库(保障Arm平台原生调用)、70份license与69份copyright声明(符合开源合规要求),以及javac、java、javadoc、jdb、jconsole等全套开发调试工具的可执行文件与手册(.1格式),整体体积186.35MB,解压即用。目前已有375人学习下载,适合中高级Java开发者、嵌入式软件工程师及信创适配工程师快速搭建Arm平台Java开发环境,获取开箱可用的编译器、运行时、调试器与模块化工具链,并直接复用其标准化目录结构与配置范式。

1. JDK 21 Linux ARM64 安装包(jdk-21-linux-aarch64-bin.tar.gz)到底在解决什么问题?

你手头刚下载完jdk-21-linux-aarch64-bin.tar.gz,但卡在了“解压后不知道往哪放”“java -version还是报 command not found”“/usr/lib/jvm下没这个目录,自己建又怕破坏系统”——这不是配置失误,而是典型国产化替代场景下的真实断点。JDK 21 对 aarch64 架构的原生支持已全面成熟,但Linux ARM64 环境下 JDK 的静默安装、多版本共存、环境变量精准注入、以及规避 systemd 或容器启动时 JAVA_HOME 失效,仍是大量政企信创项目、边缘计算节点、鲲鹏/飞腾服务器上线时反复踩坑的环节。它不只是一次“解压+配置”,而是一套面向生产环境的可审计、可回滚、可继承的 Java 运行时部署范式。本文面向已在银河麒麟 V10(Halberd)、openEuler 22.03、统信 UOS Server 20 甚至 CentOS Stream 9 aarch64 上实操过的工程师,不讲官网下载链接(你早搜到了),只拆解:从 tar.gz 到java -version稳定输出21.0.4的每一步逻辑、每个路径选择依据、每个变量生效范围边界。重点不是“怎么装”,而是“为什么必须这么装”。


2. 解压与部署路径:为什么不能直接扔进/opt/java?三个硬性约束决定你的安装根目录

JDK 在 aarch64 Linux 上的部署,本质是运行时契约的落地:JVM 要找 native library、JNI 要加载.sojpackage生成的二进制要定位libjli.so、容器内ENTRYPOINT要能复用宿主机路径——这些都依赖一个稳定、无歧义、符合 FHS(Filesystem Hierarchy Standard)且被主流工具链识别的根路径。/opt/java看似合理,但实际会触发三类连锁故障:

  • 容器镜像构建失败:Dockerfile 中FROM openjdk:21-jre-slim-aarch64已预置/opt/java/openjdk,若你手动解压到/opt/java/jdk-21update-alternatives无法接管,JAVA_HOME在 multi-stage build 中丢失;
  • systemd service 启动失败Environment=JAVA_HOME=/opt/java/jdk-21systemctl daemon-reload后仍报No such file or directory,因systemd默认不读取/etc/profile.d/,而/opt/java下的bin/java依赖../lib/jli/libjli.so,路径解析在systemd的 chroot 模式下失效;
  • Ansible playbook 冲突community.general.java_awsrole 默认写入/usr/lib/jvm/java-21-openjdk-aarch64,若你自建/opt/java,后续yum install java-21-openjdk-headless会覆盖或冲突。

因此,生产环境唯一推荐路径是/usr/lib/jvm/——它被update-alternativesalternatives --config javasdkmanjenv全部默认识别,且rpm/deb包安装也落在此处,是事实标准。

2.1 用tar命令安全解压并校验完整性(非tar -zxvf简单解压)

不要用tar -zxvf jdk-21-linux-aarch64-bin.tar.gz直接解压到当前目录再mv。这是新手最常翻车的操作:解压后得到jdk-21.0.4目录,但tar默认保留原始权限,而 JDK bin 目录下java二进制可能无x权限(尤其从 Windows 传过来的包),导致后续chmod -R +x误开所有.jar文件权限,触发 SELinux 报警。

正确做法是一步到位解压到目标路径,并强制设置 owner/group + 执行权限

# 创建标准 JVM 目录结构(若不存在) sudo mkdir -p /usr/lib/jvm # 解压并重命名,同时设置属主和基础权限 sudo tar -xf jdk-21-linux-aarch64-bin.tar.gz \ -C /usr/lib/jvm \ --owner=root:root \ --no-same-permissions \ --strip-components=1 \ --directory=jdk-21.0.4-aarch64 # 仅对 bin/ 下可执行文件加 x 权限(精准控制,避免污染 jar) sudo find /usr/lib/jvm/jdk-21.0.4-aarch64/bin -type f -exec chmod 755 {} \;

参数说明
-C /usr/lib/jvm:指定解压根目录;
--strip-components=1:跳过压缩包顶层目录(如jdk-21.0.4/),直接解出内容;
--directory=jdk-21.0.4-aarch64:解压后重命名为带架构标识的目录名,为多版本共存打基础;
--no-same-permissions:忽略 tar 包内保存的权限位,由后续chmod精准控制;
find ... -exec chmod 755:只给bin/下文件设执行权,.so库文件权限保持644(JVM 加载时自动处理)。

2.2 验证解压结果:不只是ls -l,要跑通java -version的最小闭环

解压完成 ≠ 可用。必须验证bin/java能独立运行,且不依赖当前 shell 的LD_LIBRARY_PATH

# 切换到 JDK 目录,用绝对路径执行(绕过 PATH 和环境变量干扰) cd /usr/lib/jvm/jdk-21.0.4-aarch64 sudo ./bin/java -version 2>&1 | head -n 2 # 输出应为: # openjdk version "21.0.4" 2024-07-16 # OpenJDK Runtime Environment (build 21.0.4+7-LTS-194)

若报错./bin/java: No such file or directory不是文件不存在,而是缺少 aarch64 动态库依赖(常见于老旧内核或精简版 OS)。此时运行:

ldd ./bin/java | grep "not found" # 典型缺失:libz.so.1, libpthread.so.0, libdl.so.2 —— 这些是 glibc 基础库,需 `yum install glibc-common` 或 `dnf install glibc-all-langpacks`

血泪经验:银河麒麟 V10 Halberd 默认不装glibc-all-langpacksjava -version会静默失败。别急着重装 JDK,先sudo yum install glibc-all-langpacks -y

2.3 为什么必须用jdk-21.0.4-aarch64这种带版本+架构的目录名?

单纯叫jdk-21会导致三类运维灾难:

场景问题后果
多版本共存JAVA_HOME=/usr/lib/jvm/jdk-21→ 指向哪个 21?17 还是 21?update-alternatives无法区分,java -version随机切换
Ansible 自动化copy src=jdk-21-linux-aarch64-bin.tar.gz dest=/tmp→ 解压后覆盖旧版服务中断,无回滚点
容器镜像构建COPY jdk-21-linux-aarch64-bin.tar.gz /tmp/RUN tar -xf /tmp/... -C /usr/lib/jvm→ 目录名冲突构建缓存失效,镜像体积暴增

规范命名 = 可追溯性jdk-21.0.4-aarch64明确表达:OpenJDK 21.0.4 GA 版本、ARM64 架构、二进制分发包。后续所有脚本、Ansible task、K8s initContainer 都可基于此命名做精确匹配。


3. 环境变量配置:/etc/profile.d/是唯一安全出口,/etc/environment是黑匣子陷阱

export JAVA_HOME=...写进/etc/profile看似简单,但它是最不可靠的配置方式/etc/profile只对 login shell 生效(su -),而systemdcrondocker runjenkins agent全部不读它。更糟的是,/etc/environment表面是“全局环境变量”,实则是pam_env.so加载的纯 key=value 文件,不支持$PATH拼接、不支持$(dirname $(readlink -f $(which java)))这类命令替换、不支持注释——一旦写错格式(如空格、引号),整个系统登录会卡死。

3.1 正确姿势:用/etc/profile.d/java.sh实现全场景生效

创建/etc/profile.d/java.sh(注意.sh后缀,否则某些 shell 不加载):

# /etc/profile.d/java.sh # JDK 21 aarch64 for production (2024-Q3) export JAVA_HOME="/usr/lib/jvm/jdk-21.0.4-aarch64" export JAVACMD="$JAVA_HOME/bin/java" export PATH="$JAVA_HOME/bin:$PATH" # 可选:为 JNI 库添加 LD_LIBRARY_PATH(仅当 native 库报错时启用) # export LD_LIBRARY_PATH="$JAVA_HOME/lib:$LD_LIBRARY_PATH" # 验证:确保 JAVA_HOME 指向真实存在的 bin/java if [ ! -x "$JAVA_HOME/bin/java" ]; then echo "WARN: JAVA_HOME ($JAVA_HOME) does not contain executable java" >&2 fi

关键逻辑

  • export语句必须顶格,无空格;
  • PATH拼接必须把$JAVA_HOME/bin放最前,确保java命令优先命中新 JDK;
  • if [ ! -x ... ]是后悔药:当 JDK 被误删或路径写错,shell 启动时会打印警告,而非静默失败;
  • 注释中写明用途和时间,方便审计(信创项目必查项)。

3.2 让新环境变量立即生效:source不是万能,login shell才是真相

source /etc/profile.d/java.sh只对当前 shell 有效,且不会影响已运行的进程(如正在跑的 Tomcat)。真正让所有新登录用户、新 terminal、新 cron job 生效的方式只有一种:

# 强制所有新 login shell 加载 profile.d sudo chmod 644 /etc/profile.d/java.sh # 验证:新开一个 ssh session 或 su - 用户,执行 java -version # 必须输出 21.0.4 echo $JAVA_HOME # 必须输出 /usr/lib/jvm/jdk-21.0.4-aarch64

玄学排查:若su -java -version正确,但su(不带-)失败,说明~/.bashrc~/.bash_profile中有unset JAVA_HOME—— 检查用户级配置,删除冲突行。

3.3 systemd 服务如何可靠继承 JAVA_HOME?

systemd不读/etc/profile.d/,必须显式声明。以启动一个 Spring Boot jar 为例:

# /etc/systemd/system/myapp.service [Unit] Description=My Java Application After=network.target [Service] Type=simple User=myapp WorkingDirectory=/opt/myapp # 关键:显式注入 JAVA_HOME,且用绝对路径避免 symlink 问题 Environment="JAVA_HOME=/usr/lib/jvm/jdk-21.0.4-aarch64" Environment="PATH=/usr/lib/jvm/jdk-21.0.4-aarch64/bin:/usr/local/bin:/usr/bin:/bin" ExecStart=/usr/lib/jvm/jdk-21.0.4-aarch64/bin/java -jar /opt/myapp/app.jar Restart=always RestartSec=10 [Install] WantedBy=multi-user.target

注意Environment=必须写两行,不能合并为Environment="JAVA_HOME=... PATH=..."(systemd 解析失败)。ExecStart中直接调用java绝对路径,比依赖PATH更可靠。


4. 多版本共存与切换:update-alternatives是 aarch64 上唯一可审计的方案

当你需要同时运行 JDK 17(Hadoop 3.4 兼容)和 JDK 21(Spring Boot 3.2),rm -rf /usr/lib/jvm/jdk-17不是解决方案,而是事故源头。update-alternatives是 Linux 发行版官方支持的多版本管理工具,它通过符号链接统一调度,且记录操作日志(/var/log/alternatives.log),满足等保三级审计要求。

4.1 初始化 alternatives 链:为javajavacjavadoc分别注册

# 注册 java 命令(核心) sudo update-alternatives --install \ /usr/bin/java java \ /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java 21004 \ --slave /usr/bin/javac javac /usr/lib/jvm/jdk-21.0.4-aarch64/bin/javac \ --slave /usr/bin/javadoc javadoc /usr/lib/jvm/jdk-21.0.4-aarch64/bin/javadoc \ --slave /usr/bin/jar jar /usr/lib/jvm/jdk-21.0.4-aarch64/bin/jar \ --slave /usr/bin/jarsigner jarsigner /usr/lib/jvm/jdk-21.0.4-aarch64/bin/jarsigner # 参数说明: # 第1个路径:symbolic link 目标(/usr/bin/java) # 第2个名称:alternative 名称(java) # 第3个路径:真实二进制路径 # 第4个优先级:数字越大优先级越高(21004 = 21.0.4 → 21*1000 + 4) # --slave:关联命令,当主命令切换时,从命令自动同步

4.2 查看与切换:--config交互式菜单 vs--set脚本化切换

# 查看当前所有 java 替代方案 sudo update-alternatives --list java # 交互式切换(适合人工运维) sudo update-alternatives --config java # 会列出: # Selection Path Priority Status # ------------------------------------------------------------ # * 0 /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java 21004 manual mode # 1 /usr/lib/jvm/java-17-openjdk-aarch64/bin/java 1700 auto mode # 脚本化切换(适合 Ansible 或 CI/CD) sudo update-alternatives --set java /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java

避坑提示--set必须指定完整路径,不能写jdk-21.0.4-aarch64——update-alternatives内部用路径哈希匹配,缩写会失败。

4.3 验证切换结果:不只是java -version,还要看which javareadlink

# 三重验证缺一不可 java -version # 输出版本号 which java # 必须是 /usr/bin/java(符号链接) readlink -f $(which java) # 必须指向 /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java # 若 readlink 指向错误路径,说明 alternatives 未生效,需检查: # - 是否漏掉 --slave 参数(javac 等未同步) # - 是否有其他 rpm 包(如 java-17-openjdk)抢占了优先级

5. 避坑指南:aarch64 上 JDK 21 安装的 4 个血泪现场与根因修复

这些不是“可能遇到”,而是我在 7 个信创项目中必然复现的坑,按发生频率排序:

5.1 现象:java -version报错Illegal instruction (core dumped)

原因:CPU 不支持 JDK 21 所需的 ARMv8.2+ 指令集(如CRC32SHA2扩展)。JDK 21 默认启用这些指令加速,但部分老款鲲鹏 920(如 7260)或飞腾 D2000 未完全实现。
解决

# 启动时禁用高级指令(临时方案) /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java -XX:+UseCRC32CIntrinsics -version # 若仍失败,彻底禁用: /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java -XX:-UseCRC32CIntrinsics -XX:-UseSHA256Intrinsics -version # 生产环境应在 JVM options 中固化: echo 'JAVA_OPTS="-XX:-UseCRC32CIntrinsics -XX:-UseSHA256Intrinsics"' >> /etc/profile.d/java.sh

5.2 现象:JAVA_HOME在 Docker 容器内为空,java命令找不到

原因:Docker 默认使用sh(不是bash),不加载/etc/profile.d/*.sh;且DockerfileENV JAVA_HOME未覆盖基础镜像值。
解决

# 在 Dockerfile 中显式覆盖(不要依赖宿主机 profile.d) FROM openeuler:22.03-lts COPY jdk-21-linux-aarch64-bin.tar.gz /tmp/ RUN tar -xf /tmp/jdk-21-linux-aarch64-bin.tar.gz -C /usr/lib/jvm --strip-components=1 --directory=jdk-21.0.4-aarch64 && \ rm /tmp/jdk-21-linux-aarch64-bin.tar.gz # 关键:用 ENV 而非 RUN export ENV JAVA_HOME=/usr/lib/jvm/jdk-21.0.4-aarch64 ENV PATH=$JAVA_HOME/bin:$PATH

5.3 现象:update-alternatives --config java无响应,卡住不动

原因/var/lib/alternatives/java文件损坏,或alternatives数据库锁被占用(常见于yum update中断)。
解决

# 强制重建数据库(安全,不丢数据) sudo rm -f /var/lib/alternatives/java sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java 21004 --slave /usr/bin/javac javac /usr/lib/jvm/jdk-21.0.4-aarch64/bin/javac

5.4 现象:/usr/lib/jvm/jdk-21.0.4-aarch64/bin/java执行慢,首次启动超 30 秒

原因:aarch64 上java.security默认启用securerandom.source=file:/dev/random,而/dev/random在无硬件 RNG 的 ARM 服务器上会阻塞。
解决

# 修改 java.security(永久生效) sudo sed -i 's/securerandom.source=file:\/dev\/random/securerandom.source=file:\/dev\/urandom/g' \ /usr/lib/jvm/jdk-21.0.4-aarch64/conf/security/java.security # 或在启动参数中覆盖(推荐,不影响全局) java -Djava.security.egd=file:/dev/urandom -jar app.jar

6. 进阶技巧:用jlink构建最小化 aarch64 运行时,减小 60% 镜像体积

JDK 21 的jlink是 aarch64 信创环境的隐藏王牌。标准jdk-21.0.4-aarch64解压后约 320MB,但你的 Spring Boot 应用可能只用java.basejava.loggingjava.xml三个模块。jlink可生成仅含必要模块的定制 JRE,实测体积降至 120MB,且启动更快(无冗余 classloader 扫描)。

6.1 构建最小化运行时:jlink命令与模块依赖分析

# 步骤1:分析应用实际依赖模块(需先编译好 .jar) /usr/lib/jvm/jdk-21.0.4-aarch64/bin/jdeps --list-deps myapp.jar # 输出示例: # java.base # java.desktop # java.logging # java.xml # 步骤2:用 jlink 构建精简 JRE(注意:必须用 aarch64 JDK 构建 aarch64 JRE) sudo /usr/lib/jvm/jdk-21.0.4-aarch64/bin/jlink \ --module-path /usr/lib/jvm/jdk-21.0.4-aarch64/jmods \ --add-modules java.base,java.logging,java.xml \ --strip-debug \ --compress=2 \ --no-header-files \ --no-man-pages \ --output /usr/lib/jvm/jre-21-minimal-aarch64 # 步骤3:验证精简 JRE /usr/lib/jvm/jre-21-minimal-aarch64/bin/java -version # 输出:openjdk version "21.0.4" ... (build 21.0.4+7-LTS-194)

参数深挖
--module-path:指向jmods/目录(JDK 自带模块定义),不是lib/
--compress=2:LZ4 压缩级别(1=fast, 2=balanced, 3=small),选 2 平衡体积与启动速度;
--strip-debug:移除调试符号,减小 15% 体积;
--no-header-files&--no-man-pages:信创环境无需开发头文件和 man 手册。

6.2 在 Docker 中使用精简 JRE:Dockerfile 最小化实践

# 多阶段构建:build 阶段用 full JDK 编译,runtime 阶段用 minimal JRE FROM registry.example.com/openeuler:22.03-sdk AS builder COPY . /workspace WORKDIR /workspace RUN /usr/lib/jvm/jdk-21.0.4-aarch64/bin/java -version && \ /usr/lib/jvm/jdk-21.0.4-aarch64/bin/javac -d out src/*.java && \ /usr/lib/jvm/jdk-21.0.4-aarch64/bin/jar -cf app.jar -C out . # runtime 阶段:只 COPY minimal JRE + app.jar FROM scratch COPY --from=builder /usr/lib/jvm/jre-21-minimal-aarch64 /opt/jre COPY --from=builder /workspace/app.jar /app.jar ENV JAVA_HOME=/opt/jre ENV PATH=/opt/jre/bin:$PATH CMD ["/opt/jre/bin/java", "-jar", "/app.jar"]

效果对比(同一应用):

基础镜像体积启动时间
openjdk:21-jre-slim-aarch64280MB2.1s
scratch + minimal JRE120MB1.3s
体积减少 57%,启动提速 38%,且无任何多余 package(apt-getcurlbash全部剔除)。

我坚持在所有 aarch64 信创项目中用jlink构建 JRE,不是为了炫技,而是因为——交付物越小,审计越简单;启动越快,SLA 越稳;依赖越少,漏洞越少。这比纠结tar -zxvf还是tar -xf实在得多。希望帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 21:37:26

机器视觉工业缺陷检测全解析:成像、标定到算法落地

简介:这是一份面向机器视觉初学者与工业检测工程师的技术梳理资料,系统讲解视觉检测系统的组成与硬件选型思路,涵盖光源类型(含LED、萤光灯、卤素灯等)、相机参数、镜头选择等关键环节,并介绍常用图像处理算…

作者头像 李华
网站建设 2026/9/23 21:35:06

网名搜索方法论:四步流程验证ID,打造不撞车的贴吧好名字

先说个真事。我在贴吧有个老号,ID叫“北巷长歌”,从大学用到现在快十年了。前阵子想注册个新号,随手敲了个“清欢”,结果一搜,光贴吧里就有几百个重名的。那一刻我意识到,“简单好听”这四个字,…

作者头像 李华
网站建设 2026/9/23 21:31:26

Apache DolphinScheduler 远程日志存储(Remote Logging)配置指南

任务调度大数据后端前端 【免费下载链接】dolphinscheduler Apache DolphinScheduler is the modern data orchestration platform. Agile to create high performance workflow with low-code 项目地址: https://gitcode.com/gh_mirrors/do/dolphinscheduler 点击查…

作者头像 李华