JDK21安装与环境变量配置全攻略,附Aspose.Words兼容性实测 如果你最近在折腾 JDK21多半是奔着一个关键词去LTS。JDK 21 在 2023 年 9 月正式发布是继 JDK 17 之后又一个长期支持版本免费安全补丁周期至少覆盖到 2031 年。对于还在 JDK 8 / JDK 11 上挣扎的朋友这是一个非常合适的迁移节点对于新项目直接上 JDK 21 更是当下最稳妥的默认选择。今天这篇就是我的 Day03我会把 JDK21 的下载、安装、环境变量配置、Linux/Mac/Windows 三平台实操以及大家最关心的“Aspose.Words 哪个版本兼容 JDK21”一次讲清楚。这篇文章适合谁刚接触 Java 的新手可以照着步骤一步步抄作业被环境变量坑过半天的同事可以参考我踩过的坑手里有老项目、想升级 JDK21 但又怕兼容性翻车的运维和开发也能在这里找到迁移前的自检清单。1. JDK21 是什么为什么现在值得装1.1 从 JDK8 跳到 JDK21你需要认识的几个关键特性很多团队现在还在用 JDK8不是说 JDK8 不行而是 JDK21 带来的提升真的会影响你写代码的方式。先说最让后端开发者兴奋的虚拟线程Virtual ThreadsJEP 444。传统线程池在处理高并发 I/O 时每个线程都绑定一个操作系统线程数量一上去就是灾难虚拟线程是 JVM 自己调度的轻量线程你可以近乎无限制地创建处理大量阻塞式 I/O 场景时代码写起来跟同步一样吞吐量却能往上顶几个数量级。然后是记录模式Record PatternsJEP 440和 switch 的模式匹配Pattern Matching for SwitchJEP 441。过去要拆一个嵌套对象先 instanceof 再强转再写 if 分支代码又臭又长现在可以直接在模式里声明局部变量并完成类型检查。比如对一个Shape shape做类型判断写法从“先判断再加 else if 再强转”变成了if (shape instanceof Circle c c.radius() 0)。这玩意儿写起来是真的舒坦。JDK21 里还首次加入了序列化集合接口Sequenced CollectionsJEP 431给List、LinkedHashSet、Deque等提供了一套统一的方法像getFirst()、getLast()、reversed()再也不用“第一个元素就 list.get(0)、最后一个元素就 list.get(list.size()-1)”来回切换了。另外字符串模板String TemplatesJEP 430、结构化并发Structured ConcurrencyJEP 453、分代 ZGCJEP 439这些新特性也都在这个版本里出现虽然一部分还是预览版但已经能明显感受到 Java 在往现代化语言使劲。1.2 LTS 版本怎么选Oracle JDK、OpenJDK 还是 Temurin安装 JDK21 之前第一个要做的决定不是“装”而是“装谁的”。网上搜 JDK21 下载跳出来的发行版非常多最常见的是这几种发行版维护方许可协议推荐场景Oracle JDK 21OracleOracle No-Fee Terms and ConditionsNFTC生产环境、需要 Oracle 官方商业支持Eclipse Temurin 21Adoptium 社区GPLv2 Classpath Exception通用场景我最推荐OpenJDK 21 官方构建OpenJDK 社区GPLv2 Classpath Exception想体验最纯粹的开源版本Amazon Corretto 21AmazonGPLv2 Classpath ExceptionAWS 生态、需要长期补丁Azul Zulu 21AzulGPLv2 / 商业协议嵌入式、物联网、特殊架构我个人的经验是如果没有特殊合规要求优先选 Eclipse Temurin。原因很简单Adoptium 社区维护得最活跃CI/CD 里用起来也没什么历史包袱如果你后续要上 Oracle 的付费支持或者你的生产环境跑在 Oracle 云上那再换 Oracle JDK 也不迟。需要注意Oracle 在 JDK 23 之后把 NFTC 协议又调整过但在 JDK21 这个版本上个人开发和大多数商业用途都是免费的只是每半年要留意一下许可协议的变化。2. 安装前的准备与版本下载2.1 先搞清楚你的系统架构“JDK21 安装步骤”搜出来的教程五花八门但第一步永远是确认架构。拿 Linux 服务器举例uname -m输出x86_64就下载 x64 版本输出aarch64就要下载 ARM64 版本Mac 上现在基本是 Apple Silicon检查“关于本机”里的芯片型号对应要下载 macOS ARM64 的包而不是 x64 的包。如果把架构搞错了最常见的现象是解压完之后执行java -version直接报Bad CPU type in executablemacOS或者cannot execute binary fileLinux。别问我是怎么知道的踩过一次之后我再也不跳过这个步骤。2.2 下载渠道与校验下载渠道我推荐三个Temurin 官方下载页https://adoptium.net/temurin/releases/?version21OpenJDK 社区构建https://jdk.java.net/21/Oracle JDK 下载页https://www.oracle.com/java/technologies/downloads/下载完一定不要直接解压就用先做校验。Windows 可以用certutil -hashfile 文件名.zip SHA256Linux 和 Mac 可以用sha256sum 文件名.tar.gz或者shasum -a 256 文件名.pkg。然后跟官网页面上的 SHA-256 对比一致才说明文件没有被破坏或篡改。这一步看起来麻烦但搞 CI 或者给公司服务器装环境的时候校验过的包才敢往生产环境放。2.3 先把环境变量规划好不管哪个平台JDK 能跑起来的关键就是两个东西JAVA_HOME和PATH。JAVA_HOME是让 Maven、Gradle、Tomcat、IDEA 这些工具找到 JDK 的“坐标”PATH则是让命令行能找到java、javac、jar这些命令。很多人只把 JDK 装上了却忘了配JAVA_HOME结果项目构建工具启动时找不到 JDK或者javac命令能执行但JAVA_HOME是空的。我的习惯是先把 JDK 解压到一个干净的目录比如 Windows 的C:\Dev\Java\jdk-21、Linux 的/opt/jdk-21、Mac 的/Library/Java/JavaVirtualMachines/jdk-21.jdk再去改环境变量。别把 JDK 丢在桌面或者“下载”文件夹里以后清理起来非常难受。3. Windows 安装 JDK21 的完整流程3.1 推荐用 zip 解压而不是 .msi 点击安装Windows 上装 JDK21 有两条路一是下载.msi双击安装二是我个人更推荐的.zip解压方式。.msi安装器会注册开机启动项、写一堆注册表卸载的时候往往会留下残留zip 解压则是一个纯绿色的目录想换版本直接删文件夹就行环境变量改一下指过去前后切换非常干净。下载jdk-21_windows-x64_bin.zip之后解压到C:\Dev\Java\jdk-21。注意解压后的目录结构里一定要能看到bin、lib、conf这些子目录不要把下载的 zip 文件本身解压出一个多余的嵌套目录那样配置JAVA_HOME时会找错路径。3.2 配置 JAVA_HOME 和 PATH 的详细过程右键“此电脑” - “属性” - “高级系统设置” - “环境变量”。在“系统变量”区域新建一个变量名JAVA_HOME变量值C:\Dev\Java\jdk-21系统变量如果已经有JAVA_HOME就改成当前这个路径。然后在“系统变量”里找到Path双击编辑点击“新增”加入%JAVA_HOME%\bin。这里有个常见坑很多教程让你把路径直接手敲进去但我建议一定用%JAVA_HOME%\bin这种相对变量引用以后升级 JDK 的时候只需要改JAVA_HOME一个变量不用再去动Path。设置完之后打开一个新的命令行窗口注意是新的旧窗口不会加载新环境变量执行java -version javac -version正常的话输出里应该有java version 21和javac 21.x同时能看到 Temurin 或者 Oracle 的字样。3.3 Windows 上容易踩的三个坑第一个坑是“明明配好了但java -version还是旧版本”。这通常是因为Path里%JAVA_HOME%\bin的位置排在了其他 JDK 后面Windows 会从前往后找第一个匹配的java.exe。解决办法是执行where java看看实际命中路径是哪一条把旧 JDK 的路径删掉或者让%JAVA_HOME%\bin排到最前面。第二个坑是系统里同时装了 JDK8 和 JDK21IDEA 里明明设置了 21但命令行却是 8。这类问题多半是“用户变量”里的Path和“系统变量”里的Path都在生效Shell 会优先读用户变量。我建议统一只改系统变量用户变量里的 JDK 路径全部清空。第三个坑是路径里有空格或中文比如C:\Program Files\Java\jdk-21其实问题不大但有些老工具解析带空格的路径会出错。为了省事我建立的目录一律不带空格。4. macOS 安装 JDK21 的完整流程4.1 两种安装方式图形化 PKG 和 Homebrew CaskmacOS 上装 JDK21最简单的是从 Temurin 下载.pkg安装包双击安装后系统会自动把 JDK 放到/Library/Java/JavaVirtualMachines/目录并把java软链到/usr/bin/java。这种方式对新手最友好唯一的问题是卸载不彻底下次想换版本容易残留。我比较推荐 Homebrew 用户用 Cask 方式brew install --cask temurin21装完后执行java -version应该已经能看到 21。如果之前装过其他版本的 JDKHomebrew 默认不会覆盖原来的软链这时候需要手动确认当前用的是不是 21。检查方式可以执行/usr/libexec/java_home -V这个命令会列出系统里所有的 JDK 版本和安装路径非常有用。4.2 配置 JAVA_HOMEzsh/bash 都适用macOS 从 Catalina 开始默认 shell 是 zsh所以环境变量要写在~/.zshrc里如果你还在用 bash就写在~/.bash_profile。执行echo export JAVA_HOME$(/usr/libexec/java_home -v 21) ~/.zshrc source ~/.zshrc这里用/usr/libexec/java_home -v 21而不是硬编码路径好处是即使你后来装了 JDK22、JDK23只要想切回 21这条命令会自动定位到当前机器上安装的 JDK21 实际目录比自己手写路径稳得多。我之前图省事在~/.zshrc里写死/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home结果后来升级了 JDK 版本路径变了还找不到错误源头折腾半小时才反应过来。4.3 验证安装与卸载残留处理配置完成后新开一个终端窗口依次执行java -version echo $JAVA_HOME输出类似openjdk version 21.0.2 2024-01-16 OpenJDK Runtime Environment Temurin-21.0.213 (build 21.0.213)如果echo $JAVA_HOME是空白的大概率是环境变量写进了~/.bash_profile而当前终端用的是 zsh或者source完没开新窗口。遇到 Mac 上“明明装好了但 IDEA 不认”的情况不要急着重装 JDK先在 IDEA 的 Project Structure 里把 SDK 手动指定到/Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home通常就解决了。5. Linux 服务器安装 JDK21 的完整流程5.1 新装服务器上的 tar.gz 离线安装给一台 Linux 新服务器配 JDK21最通用、最可控的方式是下载tar.gz包解压安装。用apt直接装openjdk-21-jdk虽然快但部分老发行版还在用 OpenJDK 17 或者更旧仓库里可能根本没有 JDK21或者版本滞后。离线包的优点是版本精确、与发行版解耦适合服务器上同时跑多个项目的情况。示例命令如下cd /tmp wget https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.2%2B13/OpenJDK21U-jdk_x64_linux_hotspot_21.0.2_13.tar.gz sudo mkdir -p /opt/jdk sudo tar -xzf OpenJDK21U-jdk_x64_linux_hotspot_21.0.2_13.tar.gz -C /opt/jdk sudo mv /opt/jdk/jdk-21.0.213 /opt/jdk/jdk-21解压完后先验证一下包的完整性。tar解压出来的目录里如果弹出一连串tar: x: Cannot open: No such file or directory多半是下载文件损坏或者磁盘写满别硬着头皮往下配。5.2 使用 /etc/profile.d 设置全局环境变量设置环境变量时我不用~/.bashrc而是习惯在/etc/profile.d/下新建一个脚本文件比如/etc/profile.d/jdk21.shsudo tee /etc/profile.d/jdk21.sh EOF export JAVA_HOME/opt/jdk/jdk-21 export PATH$JAVA_HOME/bin:$PATH EOF然后执行source /etc/profile或者重新登录服务器。用profile.d的好处是无论登录 shell 是 bash 还是 zsh只要走登录会话这个文件里的配置都会被加载而且多台服务器统一管理的时候只需要把同一个脚本拷贝过去环境就完全一致。这种方式比改/etc/bashrc、/etc/profile都更干净卸载时删掉一个文件就行。5.3 用 update-alternatives 管理多版本 JDK服务器上经常需要同时存在多个 JDK。比如项目 A 要求 JDK8项目 B 要求 JDK21这时候只改环境变量很容易乱。我的做法是用update-alternatives统一管理sudo update-alternatives --install /usr/bin/java java /opt/jdk/jdk-21/bin/java 2101 sudo update-alternatives --install /usr/bin/javac javac /opt/jdk/jdk-21/bin/javac 2101 sudo update-alternatives --config java把2101理解为优先级数字越大越靠前。执行sudo update-alternatives --config java之后系统会列出所有已注册的 JDK让你选择默认的java命令指向哪一条路径。javac也要单独注册否则会出现java -version是 21、javac -version却是旧版本的奇怪现象。这种场景说实话很容易碰到因为只注册java忘记注册javac的坑我踩过不止一次。需要注意update-alternatives只影响/usr/bin/java这个通用软链不会自动改JAVA_HOME。如果你的构建工具依赖JAVA_HOME还是要回到/etc/profile.d/里指定全局的那个路径两者互补使用。6. JDK21 与 Aspose.Words 的兼容性实测6.1 Aspose.Words for Java 兼容 JDK21 的版本选择搜“aspose-words 哪个版本兼容 jdk21”的人多半是生产环境里已经在用 Aspose.Words 做 Word 转 PDF、文档生成又担心升级到 JDK21 后一堆反射调用直接崩掉。直接说结论我实测下来Aspose.Words for Java 从 24.2 开始正式针对 JDK 21 做过兼容性调整我自己生产环境用的是 24.6.x在 JDK21 上已经稳定跑了几个月Word 转 PDF、DOCX 解析、模板填充都没问题。如果你还在用 23.x 或者更早的版本换到 JDK21 后有概率遇到两类报错一是java.lang.IllegalAccessErrorAspose 内部对 JDK 封装类做反射访问被模块系统拦截二是NoClassDefFoundError某个类初始化失败。这类问题在新版本里已经处理过所以我的建议很简单能升级 Aspose.Words 就升级别为了老版本故意停留在 JDK17。官方 Maven 依赖写法如下dependency groupIdcom.aspose/groupId artifactIdaspose-words/artifactId version24.6/version classifierjdk17/classifier /dependency这里有个细节有些 Aspose.Words 版本仓库里同时存在jdk17和普通的 classifier老教程只写了版本号没写 classifier。在 JDK21 上跑的时候我推荐指定jdk17这个 classifier它是 Aspose 针对高版本 JDK 编译的产物能避免很多隐性兼容问题。6.2 如果线上还在用旧版 Aspose-Words如何快速定位兼容问题升级到 JDK21 之后如果跑 Aspose.Words 报错先别急着改代码按顺序做三件事第一把异常堆栈完整打出来。很多错误在日志里只有一行Caused by往下多看几层找at com.aspose.words.*的栈帧就能知道具体是在哪个转换步骤触发的。第二检查是不是启动参数的问题。在 JDK9 之后的模块系统里有些反射访问必须加--add-opens参数如果某个内部方法被限制临时加上--add-opens java.base/java.langALL-UNNAMED可以验证是不是这个原因。但注意这只适合临时验证不能作为最终方案还是得升级版本。第三写一个最小复现用例只创建一个Document加载 DOCX再调用一次save(out.pdf)能稳定复现才好排查别拿一整个业务链路来试。6.3 给老项目迁移 JDK21 的兼容性自检清单除了 Aspose.Words老项目跳到 JDK21 还应该检查这几个点组件最低兼容版本检查方式Maven3.9mvn -versionGradle8.5gradle -versionLombok1.18.30java -jar lombok.jar检查或依赖版本Spring Boot3.2spring-boot-starter-parent版本号Tomcat10.1catalina.sh versionJDK21 对字节码版本要求很严如果你的构建工具还在用老版本的 Maven 编译器插件javax包和jakarta包混用的问题会非常刺眼。我的习惯是先跑一遍mvn clean package再跑一遍项目的单元测试把编译错误全部清掉再考虑上线。迁移到 JDK21 最怕的不是 JDK 本身出问题而是团队里有些隐性的第三方库还停留在 Java 8 时代。7. 常见问题排查与实操技巧大全7.1 命令行找不到 java 命令怎么办出现java 不是内部或外部命令Windows或者bash: java: command not foundLinux/macOS时先检查是不是 PATH 没有生效。Windows 上执行where javaLinux 上执行which java如果能输出路径说明命令在但版本不对如果输出为空说明 PATH 里根本没有 JDK 的 bin 目录。Linux 下还有个特别容易忽略的地方你明明改好了/etc/profile.d/jdk21.sh但用 SSH 登录时如果走的是非登录 shell有些 CI 工具会这样/etc/profile不会被读取。遇到这个情况在项目专用的启动脚本里显式地source /etc/profile.d/jdk21.sh或者直接把JAVA_HOME和PATH写进项目的.bashrc里。生产服务器上我更推荐前者全局脚本还是保留在profile.d里项目里只需要显式加载一次。7.2 配置完版本还是显示 JDK8 或者旧版本这个现象我调试过非常多客户的服务器根本原因几乎都是 PATH 的顺序问题。Windows 上按 [Win] 键搜索“环境变量”把%JAVA_HOME%\bin移到Path列表的最顶部Linux/macOS 上检查echo $PATH看看是不是/opt/jdk/jdk-21/bin排在了旧 JDK 路径后面。另外检查一下JAVA_HOME的最后有没有多余的斜杠或者空格我见过有人在变量值后面不小心加了空格结果java -version一直显示旧版本排查了半小时。如果你的系统里同时有 Oracle JDK、Temurin、以及某些软件自带捆绑的 JRE建议直接执行ls -l $(which java)在 Linux 上/usr/bin/java往往是一个软链指向alternatives再指向真实 JDK 路径。看清楚整个软链链路的指向你就能知道真正生效的是哪一版。7.3 IDEA、Maven、Gradle 常见的 JDK21 配置误区IDEA 里不是只设置 Project SDK 就够了。如果你用 Maven/Gradle 多模块项目还要检查 Settings - Build Tools - Maven - Runner 里的 JRE 是不是指向 JDK21Gradle 项目还要看gradle-wrapper.properties里的distributionUrl是否指定了能兼容 JDK21 的 Gradle 版本。很多人在 IDEA 里编译通过但 Maven 命令行构建时还是用系统默认的 JDK17导致release version 21 not supported之类的报错原因就在这里。Maven 项目里推荐在编译器插件中显式声明properties maven.compiler.release21/maven.compiler.release /properties用release而不是source/target因为release会顺带让编译器检查 JDK21 的新 API 是否能被正确链接能提前暴露不该引用的 JDK 内部类。7.4 JDK21 安装排查速查表现象大概率原因快速解决java -version报错找不到命令PATH 未包含$JAVA_HOME/bin添加路径并重新登录终端JAVA_HOME为空环境变量未写入当前 shell 配置文件写入~/.zshrc或/etc/profile.d版本显示为旧版PATH 中旧 JDK 排在前调整 PATH 顺序移除旧版本路径执行.java无反应只装了 JRE 没装 JDK下载包含javac的完整 JDK 包IDEA 找不到 JDKIDE 缓存未刷新File - Invalidate Caches 重启Maven 编译报 release version 21 不支持Maven 版本较老升级到 Maven 3.9javac版本和java版本不一致update-alternatives 只注册了其中一个分别注册java和javac写在最后我的几点实操体会折腾完 JDK21 之后我最深的感受是安装本身并不难难的是“你以为装好了、其实没生效”的那一刻。所以我现在不管给哪台机器配 JDK都会强制自己走完三个验证java -version看版本、javac -version看编译器、echo $JAVA_HOME看环境变量路径。三条输出全部正常才算完成。如果你用的是 Mac强烈建议直接依赖/usr/libexec/java_home -V来做 JDK 切换别再手写绝对路径了。给服务器配环境的时候能用/etc/profile.d/统一收敛环境变量就别在各种 shell 配置里散着写能省下以后极大的维护成本。JDK21 是一个很值得投入的 LTS 版本虚拟线程和记录模式带来的开发体验提升是实打实的。这篇文章的 Day03 内容就先到这里希望这套流程能让你少踩点坑。