news 2026/9/16 1:57:45

国产ARM服务器部署JDK 21实战:环境变量、多版本共存与GLIBC兼容

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
国产ARM服务器部署JDK 21实战:环境变量、多版本共存与GLIBC兼容

简介:本资源是面向Linux Arm架构设备(如树莓派、国产ARM服务器等)的Java开发环境核心组件——JDK 21官方二进制发行版,专为嵌入式开发、边缘计算及国产化平台Java应用部署提供原生支持。压缩包共386个文件,涵盖70个jmod模块文件(支撑JLink定制运行时)、38个so动态库(保障Arm平台本地调用)、69个copyright与70个license文件(符合开源合规要求),以及javac、java、jshell、jconsole、jfr等30余种核心工具的完整实现,总大小186.35MB。目前已有373人下载学习,适用于中高级Java开发者、信创适配工程师及高校嵌入式课程实践者。读者可直接解压配置JAVA_HOME与PATH,即刻开展Java程序编译、调试、性能分析与轻量级服务部署;配套工具链覆盖从开发(javac/jshell)、文档生成(javadoc)、打包(jar/jlink)到监控(jstat/jconsole/jfr)全流程,显著降低Arm平台Java环境搭建门槛。

1. 在国产 ARM 服务器上部署 JDK 21:不是解压完就完事,环境变量、符号链接和多版本共存才是真痛点

你刚从 OpenJDK 官网或国内镜像站下载了jdk-21-linux-aarch64-bin.tar.gz,双击解压?不,Linux 服务器没图形界面;tar -zxvf解完就java -version?大概率报错“command not found”或“no such file or directory”——尤其在鲲鹏、飞腾、海光等国产 ARM64 服务器上,JDK 21 的 aarch64 构建包对 GLIBC 版本、动态链接库路径、JAVA_HOME 路径规范极其敏感。这不是 Windows 下装个.exe 那么简单:aarch64 架构的 JDK 二进制包不自带系统级注册机制,必须手动完成解压路径固化、符号链接管理、shell 环境注入、以及与系统已有 Java(如 OpenJDK 17 或 vendor 提供的 JDK)的版本隔离。本文面向已能 SSH 登录国产 Linux 服务器的运维、后端或信创适配工程师,不讲“什么是 JDK”,只聚焦:如何让jdk-21-linux-aarch64-bin.tar.gz在真实生产环境(非 Docker 容器)中可复用、可验证、可回滚、且不破坏原有 Java 生态。


2. 解压与路径规划:为什么不能直接解到/opt/java/usr/lib/jvm

2.1 选择解压位置的核心逻辑:隔离性 > 习惯性

常见误区是把 JDK 解压到/opt/java/usr/lib/jvm——看似规范,实则埋下三类隐患:

  • 权限冲突/usr/lib/jvm通常由apt/yum管理,手动写入会干扰包管理器,后续apt upgrade可能覆盖或删除你的 JDK;
  • 路径硬编码风险:大量国产中间件(如东方通 TONGWEB、金蝶 Apusic)在启动脚本中硬编码JAVA_HOME=/usr/lib/jvm/java-17-openjdk-arm64,若你把 JDK 21 放进去并改名,极易引发服务启动失败;
  • aarch64 特定依赖缺失:JDK 21 aarch64 构建依赖libz.so.1libpthread.so.0等,而某些国产 OS(如银河麒麟 V10 SP1、统信 UOS 20)默认 GLIBC 版本为 2.28,但 JDK 21 编译时链接的是 GLIBC 2.31+ 符号,直接解压后java -version会报symbol lookup error

提示:优先使用/opt/jdk作为父目录,子目录严格按jdk-21.0.3+9-aarch64格式命名(含版本号+构建号),避免jdk-21这类模糊别名。这样既规避包管理器干扰,又为后续多版本共存留出结构化空间。

2.2 执行解压:tar命令的精确参数与校验动作

# 创建父目录(确保属主为普通运维用户,非 root) sudo mkdir -p /opt/jdk sudo chown $USER:$USER /opt/jdk # 进入下载目录,解压到 /opt/jdk 下(注意 -C 参数指定目标根目录) tar -zxvf jdk-21-linux-aarch64-bin.tar.gz -C /opt/jdk # 查看解压结果:确认生成的是 jdk-21.0.3+9-aarch64 目录(版本号以实际下载包为准) ls -l /opt/jdk/ # 输出应类似: # drwxr-xr-x 8 user user 4096 Jun 15 10:22 jdk-21.0.3+9-aarch64

tar -zxvf中各参数含义:

  • -z:调用 gzip 解压.gz层;
  • -x:执行解包(extract),非-c(create);
  • -v:显示详细过程,便于定位解压卡顿点(如磁盘满、权限不足);
  • -f:指定归档文件名,必须紧跟其后,顺序不可颠倒。

注意:不要用tar -xzf jdk-21-linux-aarch64-bin.tar.gz——虽然功能等价,但-f后未紧接文件名时,tar会误读为从标准输入读取,导致静默失败。这是国产 ARM 服务器上最常被忽略的tar陷阱。

2.3 验证解压完整性:检查关键文件与架构标识

解压后必须验证二进制文件是否真正适配 aarch64:

# 检查 java 二进制文件是否存在且可执行 ls -l /opt/jdk/jdk-21.0.3+9-aarch64/bin/java # 使用 file 命令确认 CPU 架构(输出必须含 "aarch64") file /opt/jdk/jdk-21.0.3+9-aarch64/bin/java # 正确输出示例: # /opt/jdk/jdk-21.0.3+9-aarch64/bin/java: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, stripped # 检查依赖库是否可解析(重点看 ld-linux-aarch64.so.1 路径) ldd /opt/jdk/jdk-21.0.3+9-aarch64/bin/java | grep "not found" # 若输出为空,说明所有动态库均存在;若出现 "not found",需安装对应 lib(如 libzstd1、libncurses5)

lddlibz.so.1 => not found,执行:

sudo apt install zlib1g # Debian/Ubuntu 系 # 或 sudo yum install zlib # CentOS/RHEL 系

3. 环境变量配置:JAVA_HOME不是写进/etc/profile就万事大吉

3.1 全局 vs 用户级配置的选择依据

  • 全局配置(/etc/profile:适用于所有用户(包括root和服务账户),但一旦配置错误,可能导致systemctl start tomcat失败(因服务进程读取该文件);
  • 用户级配置(~/.bashrc:仅影响当前 shell 会话,适合开发测试,但crontabsystemd服务无法继承;
  • 最佳实践为 JDK 21 单独创建/etc/profile.d/jdk21.sh,利用 shell 启动时自动 source 的机制,既全局生效,又物理隔离,便于启停。
# 创建 profile.d 配置文件(root 权限) sudo tee /etc/profile.d/jdk21.sh << 'EOF' #!/bin/bash # JDK 21 for aarch64 - DO NOT EDIT MANUALLY export JAVA_HOME=/opt/jdk/jdk-21.0.3+9-aarch64 export PATH=$JAVA_HOME/bin:$PATH EOF # 设置执行权限(profile.d 下文件需可执行才被 source) sudo chmod +x /etc/profile.d/jdk21.sh

提示/etc/profile.d/下的.sh文件会在/etc/profile末尾被for i in /etc/profile.d/*.sh; do ...循环加载,比直接修改/etc/profile更安全——升级系统时不会被覆盖,卸载时只需rm /etc/profile.d/jdk21.sh即可彻底清理。

3.2 验证环境变量生效:区分登录 Shell 与非登录 Shell

配置后必须验证,且要区分两种 Shell 类型:

  • 登录 Shell(如 SSH 登录、su -):会完整加载/etc/profile/etc/profile.d/*.sh
  • 非登录 Shell(如bash -c "java -version"crontab中的命令):仅加载~/.bashrc,不加载/etc/profile

因此,必须测试两种场景:

# 场景1:新开一个 SSH 会话,直接执行 java -version # 应输出: # openjdk version "21.0.3" 2024-04-16 # OpenJDK Runtime Environment (build 21.0.3+9-1) # OpenJDK 64-Bit Server VM (build 21.0.3+9-1, mixed mode, sharing) # 场景2:非登录 Shell 测试(模拟 crontab) bash -c 'echo $JAVA_HOME && java -version' # 若 $JAVA_HOME 为空,则说明非登录 Shell 未加载 profile.d,需在 ~/.bashrc 中追加: echo 'source /etc/profile.d/jdk21.sh' >> ~/.bashrc

3.3 多版本共存方案:用update-alternatives管理java命令软链

当系统已存在 JDK 17(如/usr/lib/jvm/java-17-openjdk-arm64),直接覆盖JAVA_HOME会导致其他服务异常。正确做法是用update-alternatives注册多个 Java 实例:

# 为 JDK 21 注册 alternatives(--install 语法:命令名、链接名、目标路径、优先级) sudo update-alternatives --install /usr/bin/java java /opt/jdk/jdk-21.0.3+9-aarch64/bin/java 2103 \ --slave /usr/bin/javac javac /opt/jdk/jdk-21.0.3+9-aarch64/bin/javac \ --slave /usr/bin/jar jar /opt/jdk/jdk-21.0.3+9-aarch64/bin/jar # 为 JDK 17 注册(假设已存在) sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-17-openjdk-arm64/bin/java 1700 \ --slave /usr/bin/javac javac /usr/lib/jvm/java-17-openjdk-arm64/bin/javac \ --slave /usr/bin/jar jar /usr/lib/jvm/java-17-openjdk-arm64/bin/jar # 交互式切换默认 java(会列出所有注册项,输入编号选择) sudo update-alternatives --config java # 查看当前配置状态 update-alternatives --display java
优先级路径状态
2103/opt/jdk/jdk-21.0.3+9-aarch64/bin/java手动选择
1700/usr/lib/jvm/java-17-openjdk-arm64/bin/java自动模式

注意--slave参数确保javacjar等配套命令与java同步切换,避免java -version是 JDK 21 但javac -version是 JDK 17 的混乱。


4. 符号链接与路径规范化:解决java -cp找不到 tools.jar 的经典问题

4.1 JDK 21 移除了tools.jar,但旧脚本仍可能引用它

JDK 9 起模块化后tools.jar已废弃,JDK 21 彻底移除。但部分国产中间件启动脚本(如某政务平台 Tomcat 插件)仍包含:

# 错误示例(JDK 21 下会报 NoClassDefFoundError) CLASSPATH="$JAVA_HOME/lib/tools.jar:$CLASSPATH"

解决方案不是降级 JDK,而是用符号链接伪造兼容路径

# 在 JDK 21 目录下创建空的 tools.jar(满足 classpath 存在性检查) touch /opt/jdk/jdk-21.0.3+9-aarch64/lib/tools.jar # 创建指向 JRT 文件系统的符号链接(JDK 21 的核心类库位于 jrt-fs.jar) ln -sf $JAVA_HOME/lib/jrt-fs.jar /opt/jdk/jdk-21.0.3+9-aarch64/lib/tools.jar

验证链接有效性:

ls -l /opt/jdk/jdk-21.0.3+9-aarch64/lib/tools.jar # 输出应为:tools.jar -> /opt/jdk/jdk-21.0.3+9-aarch64/lib/jrt-fs.jar

4.2 修复JAVA_HOME路径中的空格与特殊字符问题

国产 OS 中文路径(如/opt/软件/jdk)或用户目录含空格(/home/张三/jdk)会导致JAVA_HOME解析失败。强制使用无空格路径:

# 检查当前 JAVA_HOME 是否含空格 echo $JAVA_HOME | grep " " # 若有输出,立即修正: sudo sed -i 's|/home/张三/jdk|/opt/jdk/jdk-21.0.3+9-aarch64|g' /etc/profile.d/jdk21.sh source /etc/profile.d/jdk21.sh

4.3 验证 CLASSPATH 与模块路径:java --list-modules是终极检测手段

JDK 21 默认启用模块系统,-cp参数行为与 JDK 8 不同。用以下命令验证模块加载是否正常:

# 列出所有可用模块(应包含 java.base、java.desktop 等) java --list-modules | head -10 # 尝试加载核心模块(无报错即通过) java --add-modules java.desktop --module java.desktop/sun.awt.X11.XToolkit # 检查 JVM 启动参数是否被污染(常见于国产 OS 预装的 java-wrapper 脚本) java -XshowSettings:properties -version 2>&1 | grep -E "(java.home|os.arch)" # 正确输出中 os.arch 必须为 aarch64,java.home 必须为 /opt/jdk/jdk-21.0.3+9-aarch64

5. 国产 ARM 环境专项排错:GLIBC 版本、SELinux 与中文乱码三连击

5.1 GLIBC 版本不匹配:versionGLIBC_2.34' not found` 的根治方案

JDK 21 官方 aarch64 构建要求 GLIBC ≥ 2.34,但麒麟 V10 SP1 默认为 2.28。强行运行会报:

/opt/jdk/jdk-21.0.3+9-aarch64/bin/java: /lib64/libc.so.6: version `GLIBC_2.34' not found

不可行方案:升级系统 GLIBC(会破坏整个 OS)。
可行方案:使用patchelf修改 JDK 二进制的 GLIBC 依赖版本(需提前安装patchelf):

# 安装 patchelf(源码编译,避免包管理器版本过旧) wget https://github.com/NixOS/patchelf/releases/download/0.17.2/patchelf-0.17.2-x86_64-apple-darwin.tar.gz # 注意:aarch64 服务器需从源码编译,此处省略编译步骤,假设已安装 # 查看当前依赖的 GLIBC 版本 readelf -V /opt/jdk/jdk-21.0.3+9-aarch64/bin/java | grep -A5 "Version definition" # 将 GLIBC_2.34 替换为系统存在的 GLIBC_2.28(谨慎操作!先备份) cp /opt/jdk/jdk-21.0.3+9-aarch64/bin/java{,.bak} patchelf --replace-needed libc.so.6 libc.so.6 /opt/jdk/jdk-21.0.3+9-aarch64/bin/java

警告:此操作有风险,仅在确认 JDK 功能无缺失时使用。更稳妥方式是联系 JDK 提供方获取 GLIBC 2.28 兼容构建版,或使用 Alibaba Dragonwell 21(专为国产 OS 优化)。

5.2 SELinux 强制模式拦截:Permission denied的静默杀手

在中标麒麟、银河麒麟等开启 SELinux 的系统中,java进程可能因策略限制无法访问/tmp或网络:

# 检查 SELinux 状态 sestatus # 若为 enforcing,临时设为 permissive 观察(生产环境勿长期使用) sudo setenforce 0 # 查看拒绝日志(需先安装 setroubleshoot) sudo ausearch -m avc -ts recent | audit2why # 典型输出: # type=AVC msg=audit(1718523456.123:456): avc: denied { execute } for pid=12345 comm="java" path="/opt/jdk/jdk-21.0.3+9-aarch64/bin/java" dev="sda1" ino=67890 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=system_u:object_r:default_t:s0 tclass=file permissive=0 # 生成并加载自定义策略(永久解决) sudo grep java /var/log/audit/audit.log | audit2allow -M myjdk sudo semodule -i myjdk.pp

5.3 中文路径与文件名乱码:tar解压后文件名显示为??.txt

根源是tar默认使用Clocale 解码 UTF-8 文件名。修复方法:

# 解压时指定 locale LC_ALL=C tar -zxvf jdk-21-linux-aarch64-bin.tar.gz -C /opt/jdk # 或设置系统 locale(推荐) echo 'LANG="zh_CN.UTF-8"' | sudo tee -a /etc/environment echo 'LC_ALL="zh_CN.UTF-8"' | sudo tee -a /etc/environment source /etc/environment

验证:

locale | grep -E "(LANG|LC_ALL)" # 必须输出 zh_CN.UTF-8

最后,执行一次全链路验证:

# 1. 环境变量 echo $JAVA_HOME # 2. 命令路径 which java # 3. 版本与架构 java -version # 4. 模块加载 java --list-modules | wc -l # 应大于 100 # 5. 中文支持(输出“你好”不乱码) java -cp /opt/jdk/jdk-21.0.3+9-aarch64/lib/jrt-fs.jar \ --add-modules java.base \ -m java.base/java.lang.System \ out.println("你好")

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

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

多相机统一坐标系统标定实战:从内参到九点标定全流程解析

直接一点&#xff1a;多相机标定之所以让人头疼&#xff0c;不是相机本身难搞&#xff0c;而是“各说各话”的坐标系让人崩溃。现场三个相机各测各的&#xff0c;A相机说零件在(100, 200)&#xff0c;B相机说在(150, 180)&#xff0c;机械手到了位置却抓了个空——问题不在视觉…

作者头像 李华
网站建设 2026/9/16 1:57:04

Aspose.Words for Java 批量合并 Word 文档实战指南

简介&#xff1a;本资源是一套基于Java实现Word文档智能合并与内容替换的轻量级工具方案&#xff0c;面向Java开发工程师及办公自动化需求者&#xff0c;解决多份Word报告、合同或模板批量整合时页眉页脚丢失、批注遗漏、格式错乱等痛点。资源包共2个文件&#xff08;1个核心Ja…

作者头像 李华
网站建设 2026/9/16 1:55:33

赣州做网站推广避坑指南:新手必看5大注意事项

赣州做网站推广避坑指南:新手必看5大注意事项 在赣州找建站公司,最怕的不是没效果,而是钱花多了效果却稀烂。很多老板第一次接触网站推广,拿着预算去询价,对方张口就是“全包价”,签完合同才发现,所谓的推广只是帮你发了几条新闻稿,或者把关键词堆在网页标题里,根本不带量。这种“高价低效”的坑,我见得太多了。…

作者头像 李华
网站建设 2026/9/16 1:55:16

盲人导航车双栈开发:Python+C语言实现混合A*与DWA高效避障

简介&#xff1a;面向毕业设计、课程设计及项目开发场景&#xff0c;这套基于路径规划的智能盲人导航车项目采用Python与C语言混合开发&#xff0c;实现了上位机控制下的小车导航与高效避障&#xff0c;适合嵌入式、智能控制方向的本科生及开发者参考扩展。资源共76个文件&…

作者头像 李华
网站建设 2026/9/16 1:54:47

PrintExp UV打印主界面操作地图:四象限逻辑与工艺参数真相

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 1:54:21

抖音短链接生成与解析:原理、方案与避坑指南

做抖音相关的数据分析或者自动化工具时&#xff0c;十有八九都会碰到同一个问题&#xff1a;拿到手的视频链接是https://v.douyin.com/xxxxx/这种短连接&#xff0c;看着很规整&#xff0c;可一旦想基于它做点什么——批量检测链接是否失效、抓取作品信息、生成自己的分享物料—…

作者头像 李华