简介:面向 Java 开发者的 OpenJDK 21 的 64 位 Windows 压缩包,源自甲骨文公司开源项目的早期访问版本,适合希望在 64 位 Windows 系统上体验新特性、进行应用开发验证的开发者。压缩包共包含 484 个文件,整体大小约 189.2MB,核心由动态链接库、模块描述、可执行程序等构成,另有许可声明、说明文档、安全策略和证书配置等辅助内容,解压后即可获得 Java 编译器、运行时环境及文档生成器等常用开发工具。已有 567 人学习,该版本属于非长期支持的早期访问版,更适合关注 Java 最新进展、愿意尝鲜的开发者用于本地实验。通过安装可快速搭建 OpenJDK 21 测试环境,体验 JDK 增强提案中的新功能;同时借助模块、许可和安全策略等文件,也能深入理解 OpenJDK 的发布结构与组成部分。压缩包内含较完整的常规 JDK 目录布局,用户可依据自身项目需要,将不同组件用于日常开发、持续集成或兼容性验证场景;该压缩包也适合教学演示、本地沙箱测试和特性预研,可作为在离线环境中搭建 Java 工具链的备用安装包。
1. openjdk 21 win x64 到底是什么:别把 JRE 当 JDK
在 Windows x64 上做 Java 开发,openjdk 21 win x64 是绕不开的运行时与编译器组合包。很多人以为下载一个几十 MB 的安装包、点完下一步就能写 Java,结果打开命令行输入javac直接报「不是内部或外部命令」;还有人下载时选了 x86 版本,装出来的却是 32 位 JRE,连java -version都看不出问题。这个标题指向的其实是四件事:JDK 21 的工具链、Windows x64 的架构匹配、免安装或安装包两种交付形态,以及让java/javac在任意终端可用的环境变量配置。它能解决的是你从「装完」到「能编译运行」之间那一整段没人给你讲清楚的空白。
1.1 解压安装与目录规划
openjdk 21 win x64 最常见的安装方式不是双击 exe,而是下载 zip 压缩包直接解压。JDK 本身不需要注册表、不需要依赖注入,解压完就有了完整的bin、lib、conf目录。我一般会把 JDK 放在一个不带空格、不带中文、不带权限限制的路径下,比如C:\tools\jdk-21。
C:\tools\jdk-21 ├── bin\ # java、javac、jar、jlink 等可执行文件 ├── conf\ # 运行时配置文件 ├── lib\ # 类库与模块镜像 ├── legal\ # 许可证与第三方声明 └── release # 版本信息,包含 JAVA_VERSION 与 OS_ARCH解压之后先看release文件,确认OS_ARCH="x86_64",这一步能帮你排除下载错误架构包的风险。如果你顺手把压缩包删了,这次安装就算完成了一半——后面还要配置JAVA_HOME和PATH,这两个环境变量才决定命令行能不能找到java.exe。
1.2 环境变量配置:JAVA_HOME 与 PATH
配置环境变量有两个层面:用户变量和系统变量。对于单机开发,我建议只改用户变量,避免影响其他系统服务。在 Windows 11 里搜索「编辑账户的环境变量」,然后做两步操作:
新建用户变量: 变量名:JAVA_HOME 变量值:C:\tools\jdk-21 编辑用户的 PATH: 新增一行:%JAVA_HOME%\bin两个变量缺一不可:JAVA_HOME是很多构建工具(Maven、Gradle、IDE)寻找 JDK 的约定位置,而PATH里的%JAVA_HOME%\bin让java和javac可以直接被命令行执行。配置完成后,打开一个新的 cmd 窗口验证:
java -version javac -version注意必须开「新窗口」,因为旧窗口的环境变量是在启动时快照的,配置改了也不会自动刷新。如果java -version能输出版本而javac报错,基本可以断定 PATH 里以前装过 JRE,而javac.exe只存在于 JDK 的 bin 目录中——这个问题后面专门讲。
1.3 用什么命令设置环境变量更省事
如果你不喜欢可视化界面,用 PowerShell 设置环境变量的命令同样可达,而且更适合批量脚本化:
[Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\tools\jdk-21", "User")这条命令的第三个参数User表示写入用户级环境变量,持久化保存在注册表里,不需要管理员权限。与之相比,传统的setx JAVA_HOME "C:\tools\jdk-21"虽然也能写入,但有一个知名缺陷:它把整条 PATH 读入并重写,存在 1024 字符的截断风险。如果之前有人在用户 PATH 里写了几条长值,setx会把后面的内容截掉。所以在 Windows 上操作环境变量,我倾向用[Environment]::SetEnvironmentVariable而不是setx。
环境变量设置完之后,有个小细节值得留意:配置写入的路径不要写成带尾斜杠的形式,也不要解析%JAVA_HOME%到一半。后续如果换 JDK 版本,只需要把JAVA_HOME改成一个新路径,PATH 里的%JAVA_HOME%\bin不用动,这也是这种约定被广泛采用的根本原因。
1.4 临时变量:脚本内想换 JDK 的救急方案
有些场景你暂时不想改全局变量,只是想在某个具体脚本里用另一个 JDK。常见做法是在脚本开头临时指定:
set "JAVA_HOME=C:\tools\jdk-21" set "PATH=%JAVA_HOME%\bin;%PATH%"这段命令必须写在每个需要执行 Java 的脚本里,注意用引号包裹路径——Windows 的set命令对空格非常敏感,不带引号会出现C:\tools\jdk-21后半部分被当成下一段命令的问题。这种做法的好处是不污染系统环境,适合 CI 里的回归测试脚本或临时对比不同 JDK 版本的构建行为。
到这里,openjdk 21 win x64 的安装和配置链路已经完整。下一章讨论实际使用中绕不开的 IDE 和构建工具对接,以及多版本 JDK 并存时,命令行窗口里究竟哪个java在生效。
2. exe 安装器与 zip 包怎么选:两者差异和适用场景
2.1 exe 安装器的隐藏行为
很多公开发行的 OpenJDK 构建都会同时提供 exe 安装器,好处是界面化、自动写环境变量、自带卸载入口。但要注意,部分安装器默认会把 JDK 装到C:\Program Files\...,这个路径带空格,部分旧版构建工具或脚本如果没给路径加引号,就会在解析Program Files时断开。另一个更隐蔽的问题是,有些 exe 安装器默认只勾选「JRE」或「公共组件」,没勾选「开发工具」,装完后javac.exe根本不存在。
所以在动手之前,先想清楚你的诉求。如果你要跑的是已打包好的 jar,只需要 JRE,但你要做的是编译和调试,就得确保安装器选项里勾上了完整 JDK。我一般建议下载 zip 包自己解压,原因很直接:你能清楚地知道 JDK 物理位置在哪,bin 目录里有哪些工具,将来删除时直接删目录即可,不依赖卸载程序。
2.2 安装版本的架构与位数校验
无论选择 exe 还是 zip,第一步都要确认「win x64」真的对应你的系统位数。Windows 上有一个容易被忽略的细节:任务管理器显示「基于 x64 的处理器」不代表操作系统一定是 64 位,更不代表你的 JDK 一定会选择 64 位版本。下载时误选 x86,装完也能跑,但 JVM 最多只能吃 4GB 内存,java -version输出时也不会直接告诉你「32-Bit」,需要自己看:
java -XshowSettings:properties -version 2>&1 | findstr "os.arch sun.arch.data.model"如果os.arch显示x86或者sun.arch.data.model为32,说明当前 java.exe 是 32 位 JVM。对 Java 21 这种面向云原生和容器优化的版本,32 位 JVM 已经没有太大意义,堆内存上不去,虚拟线程的优势也发挥不出来。真在调查这个问题的开发者,不少是因为java -version里没有明确标识位数而迟疑——这时候用上面的命令一行就能判定。
2.3 免安装 zip 包的目录迁移
免安装版本还有一层好处:可以在多台机器之间复制。只要目录结构完整且release文件里标记了JAVA_VERSION="21",把整个文件夹压缩后拷到另一台 Windows 电脑,重新设置JAVA_HOME指向新路径就能直接用。这个特性对临时开发机和离线环境尤其友好。
不过目录迁移有一点要留意:不要只拷贝bin目录,JDK 运行时依赖lib和conf,单独抽出bin肯定会报Could not find or load main class。如果某开发者不小心把java.exe单独拷出去用,随后必然发现-version能执行但运行代码时崩掉,这就是典型的「移动不完整」的翻车案例。
2.4 常见构建版本的差异对比
| 对比项 | zip 免安装版 | exe 安装器版 |
|---|---|---|
| 环境变量写入 | 手动配置 | 安装器可选自动配置 |
| 卸载 | 删目录 | 控制面板卸载 |
| 功能完整性 | 完整 JDK | 看安装选项,默认可能不含 javac |
| 多版本并存 | 轻松,目录各自独立 | 可能互相覆盖 PATH |
| 适合场景 | 开发、多 JDK 切换、临时服务器 | 不熟悉命令行的入门用户 |
表格里最值得留意的行是最后一行:多版本并存。OpenJDK 21 和 JDK 17 在同一台 Windows 上完全可以通过目录分离来共存,可 exe 安装器会在 PATH 里插入自己的条目,反而容易造成新旧版本冲突。如果你日常工作需要在多个 JDK 间切换,zip 包是更省心的选择。
3. 让 javac 随手可用:用户变量与系统变量的优先级真相
3.1 哪个变量说了算
Windows 查找命令的顺序是:当前目录 → 用户 PATH → 系统 PATH。很多人都不知道这个顺序,于是明明在「系统变量」里配置了一个 JDK 17,又装了 JDK 21 到「用户变量」,打开 cmd 输入java -version却发现还是旧的。原因就在于用户变量的优先级高于系统变量。这不是凭感觉判断的,你可以在 cmd 里执行下面这条命令查看解析结果:
where java输出会列出从 PATH 中依次找到的所有java.exe位置。第一行就代表实际生效的那一个。如果第一行指向的是C:\Program Files\Common Files\Oracle\Java\javapath之类的外部路径,请直接进「系统属性 → 环境变量」检查,很可能是安装 JRE 时自动加进去的残留项。
3.2 残留项清理与 JAVA_HOME 不一致的后果
我遇到过一种非常经典的故障:java -version显示的版本和javac -version显示的版本完全不一样。其中一个输出 21,另一个输出 1.8。原因就是 PATH 里既有新 JDK 的%JAVA_HOME%\bin,又有旧 JRE 注册的路径,而两者在 PATH 中的先后顺序不一致。
处理办法是把 PATH 中与 Java 相关的条目全部列出来,逐条确认指向哪个目录,然后只保留一条%JAVA_HOME%\bin。比如下面这样的操作:
echo %PATH%重点观察有没有:
C:\Program Files\Common Files\Oracle\Java\javapathC:\Program Files\Java\jdk1.8.0_...\binC:\jdk-11\bin
只要这些旧路径还在,where java的结果就不会稳定。正确做法是全部移除,把%JAVA_HOME%\bin放在 PATH 较靠前的位置。顺带留意:不要同时保留两个指向不同 JDK 的bin条目,这正是黑匣子类问题的常见根源。
3.3 环境变量不生效的排查顺序
配置完成后立刻在新窗口执行java -version,如果java命令仍然报错或显示旧版本,按这个顺序排查:
- 确认当前窗口真的新开了,而不是在旧窗口按了回车
- 执行
set JAVA_HOME,看变量值是否为完整路径且不含引号 - 执行
echo %PATH%,看%JAVA_HOME%\bin是否被正确展开成C:\tools\jdk-21\bin - 执行
where java,看第一个结果指向哪个目录 - 检查是否安装了 Windows 自带的 JRE 或其它 Java 运行时
最后一条尤其重要。Windows 系统里可能残留一个javapath,它指向的是早期安装的 JRE,这个目录常常排在 PATH 很靠前的位置,导致你明明配置了 JDK 21,java -version却死活用不了。建议在命令行中执行where java,看第一个结果指向哪个目录——这是排查中的第一步,也是最有效的一步。
3.4 环境变量修改后不刷新的补充方案
有些开发者会遇到一个问题:环境变量改对了、PATH 里也排除了旧路径,但 IDE 或正在运行的进程仍然拿不到新的 JDK。因为进程在启动时就读取了环境变量,不会动态刷新。最简单的解决办法就是重启相关进程;如果不想重启整个电脑,可以使用 Windows 提供的广播机制让资源管理器刷新:
$env:JAVA_HOME = "C:\tools\jdk-21" $env:PATH = "$env:JAVA_HOME\bin;" + $env:PATH这是写入当前 PowerShell 会话的临时方案,用来尽快测试。真正要持久化还是回到第 2 章[Environment]::SetEnvironmentVariable。注意,某些 IDE 启动时会缓存 JVM 路径,即便系统环境变量已经改掉,它依然会用启动时的旧的java.exe,这时需要在 IDE 设置里主动指定新的 JDK 路径,而不是只依赖系统环境变量。
4. openjdk 21 win x64 避坑:安装配置中最常踩的 5 类问题
4.1 javac 不是内部或外部命令
现象:java -version输出正常,但javac直接报错「不是内部或外部命令」。
原因:PATH 里有 JRE 的bin目录,但没有 JDK 的bin目录。JRE 里只有java.exe,没有编译器。
解决:确认JAVA_HOME指向的目录确实是 JDK,而不是 JRE;然后执行echo %PATH%查看是否包含%JAVA_HOME%\bin。如果用户变量 PATH 里没有,补上;如果有但还报错,检查这个变量是否放在 cmd 可以访问的范围内,并重新开窗口。最后用where javac确认能定位到。
4.2 java -version 显示版本与期望不一致
现象:明明装了 openjdk 21,java -version却显示 1.8 或者 17。
原因:PATH 中排在前面的条目指向旧 JDK 或旧 JRE,新 JDK 的路径排在后面,系统优先找到了旧版本。
解决:用where java列出所有 java.exe,把冲突的旧路径移除;或者直接把%JAVA_HOME%\bin移到 PATH 最靠前的位置。另外一种快速验证方式是执行"%JAVA_HOME%\bin\java" -version,这样可以绕过 PATH 直接验证 JAVA_HOME 指向的版本。
4.3 zip 包解压后 bin 目录里没有 java.exe
现象:从某个发行版下载了openjdk-21_windows-x64_bin.zip,解压后bin目录只有一堆 dll,没有可运行的 exe。
原因:有些发行版的 zip 包是「jdk 运行时内部结构」,需要点击 exe 安装器才生成最终可执行文件,或者下载的其实是调试符号包或源码包而非二进制包。
解决:回下载页核对文件名。真正的二进制包一般体积较大,解压后bin目录里肯定有java.exe、javac.exe、jar.exe。如果下载的是.zip且解压第一层还套着另一个目录,别急着配环境变量,先确认最内层目录确实包含了bin。遇到这种情况,重下对应架构的二进制包即可。
4.4 JAVA_HOME 指向的路径被删除后启动报错
现象:删除旧 JDK 目录但没有及时修改JAVA_HOME,任何 Java 程序都报「无法启动此程序,因为计算机中丢失 java.exe」之类的错误。
原因:JAVA_HOME仍然指向一个不存在的目录,PATH 里通过%JAVA_HOME%\bin也无法解析出 java.exe。
解决:把JAVA_HOME改为实际存在的 JDK 目录,或临时在命令行设置set JAVA_HOME=C:\tools\jdk-21救急。平时更新 JDK 版本时,先改环境变量再删旧目录,这个顺序能避免很多无效报错。
4.5 PowerShell 中 java 可用但 cmd 不可用
现象:在 PowerShell 里执行java -version能通过,但在 cmd 或其它软件里调用 java 失败。
原因:PowerShell 可能配了 profile 脚本,在会话启动时给 PATH 加了 JDK,而这个配置只对 PowerShell 生效。
解决:不要依赖 profile 补路径,把 JDK 路径固化到系统用户环境变量。常见做法是检查用户变量和系统变量中是否有完整路径,确保不依赖 shell 初始化脚本。同样的问题也出现在 Git Bash 或 WSL 场景下,它们的 PATH 由各自的启动脚本控制,跨 shell 调用时需要统一配置。
5. 进阶:验证安装、日常使用和常用命令组合
5.1 用官方自带工具验证安装完整性
安装完成后,别只跑java -version,起码验证三件事:编译器版本、运行时版本、jlink 模块工具是否可用。这跟你下载的包是不是完整 JDK 息息相关:
java -version 2>&1 javac -version jlink --version如果三行命令都输出正常,那么 JDK 工具链基本可用。还有一个常被忽略的点是检查架构位数:
java -XshowSettings:properties -version 2>&1 | findstr /i "os.arch"输出os.arch = amd64时,说明当前运行的 JVM 是 64 位。对 openjdk 21 win x64 来说,这是最直接的确认方式。
5.2 编译运行一个最小 Java 程序
配置已经完成,写一个最小程序走通编译和运行:
public class HelloJdk21 { public static void main(String[] args) { System.out.println("Hello OpenJDK 21"); System.out.println(System.getProperty("java.version")); } }保存为HelloJdk21.java后在 cmd 中执行:
javac HelloJdk21.java java HelloJdk21如果看到版本号是 21,说明javac和java用的确实是同一个 JDK。这里有一个要注意的点:编译和运行用的是同一个 bin 目录下的工具,如果javac来自 JDK 21 而java来自旧 JRE,编译能通过但运行时版本会不一致。这也是为什么前面反复强调 PATH 里的残留项要清理干净。
5.3 IDE 中新导入 JDK 或切换版本
日常开发基本都会用 IDE。在 IDEA 或 Eclipse 中,你可以在项目结构设置里直接添加一个新的 SDK:
IDE 设置路径(以 IDEA 为例): File → Project Structure → Project → SDK → Add JDK 选择 C:\tools\jdk-21添加之后,记得把「Project language level」设为 21,否则即便 JDK 是 21,语法特性也可能被限制在旧版本。对于 Maven 项目,还要确认pom.xml里配了maven.compiler.release为 21,否则 Maven 会基于自己所在的 JAVA_HOME 选择编译源级别,出现「语法正确但编译报错」的误伤场景。
5.4 用 javac 指定编译版本,避免隐式升级
在一个需要保持兼容性的模块里,可以用--release参数手工控制字节码目标版本,防止新 JDK 把新特性偷偷编进去:
javac --release 17 HelloJdk21.java这里--release 17的含义是将编译目标的 API 和字节码版本都锁定为 Java 17。对同时维护多个项目的开发者来说,这是一个很值得养成的习惯。尤其在使用 OpenJDK 21 但部署环境可能只有 Java 17 的运行时的情况下,编译阶段的版本控制远比事后 Debug 来的省力。
5.5 常用 JVM 启动参数与验证习惯
日常运行 Java 程序时,最常用的参数是堆内存和 GC 打印。在 Windows cmd 环境下,可以直接这样设置:
java -Xms512m -Xmx2g -XX:+PrintGCDetails -jar your-app.jar-Xms512m:初始堆大小-Xmx2g:最大堆大小-XX:+PrintGCDetails:GC 日志输出,排查内存问题很管用
如果你在本地验证一个小型服务,初始堆和最大堆相同可以省去 JVM 动态扩容的开销,但不建议在服务器上这么做。另外,Java 21 的虚拟线程是正式特性,如果你写的是 IO 密集型的并发任务,把线程创建方式从 new Thread 改成 Thread.ofVirtual().start,会有非常直观的资源占用改善。不过虚拟线程的具体适用场景要在压测中验证,不要盲写在所有服务端代码里。
5.6 多版本 JDK 共存时的日常操作
多版本并存的情况下,我会维护一个简单的切换脚本。这里记录两个典型做法:临时会话切换和永久修改。
set "JAVA_HOME=C:\tools\jdk-17" set "PATH=%JAVA_HOME%\bin;%PATH%"上面是临时切换,只对当前命令行生效,适合验证某个旧项目是否兼容。如果你想恢复成 21:
set "JAVA_HOME=C:\tools\jdk-21" set "PATH=%JAVA_HOME%\bin;%PATH%"这种切换方式简单、直观,唯一的代价是每次新开会话都要重新执行。要是你希望某个项目固定使用 JDK 21,直接在 IDE 和构建工具里配置即可,不需要频繁改系统环境变量。经历过几次因为全局切版本导致旧项目编译不过的翻车之后,我现在的习惯是:全局环境变量只指向最常用的 JDK,项目级 JDK 一律在 IDE 和构建工具里单独指定。这套组合在 openjdk 21 win x64 上跑得很稳,希望帮到你。
本文还有配套的精品资源,点击获取