简介jdk-17.0.3.1jdk-17_windows-x64_bin.zip是面向 Windows x64 平台的 Java SE 长期支持版本安装包适合 Java 开发者、后端工程师及计算机专业学生搭建本地开发与运行环境。作为 Oracle 免费条款下可商用、可再分发的 JDK 发行版它既能满足日常编码编译也可用于生产部署与教学实验。压缩包共 416 个文件约 171.62MB包含 86 个 dll 动态库、35 个 exe 可执行程序、71 个 jmod 模块文件以及 license、copyright、properties、policy 等许可与配置文档另有 cacerts 证书库、jvm.cfg 虚拟机配置和 release 版本说明结构完整、开箱即用。目前已有 1396 人学习下载覆盖从环境搭建到模块化开发的常见需求便于读者快速获得官方原版工具链省去自行拼装组件的麻烦。1. 为什么我硬盘里永远留着一份 jdk-17.0.3.1 的 windows-x64 bin.zip上周帮同事排查一个 Spring Boot 3 项目启动就崩的问题日志里一行UnsupportedClassVersionError: class file version 61.0他本地装的是 JDK 8。换版本、清缓存、重配JAVA_HOME折腾半小时才跑起来。这种事我遇到过太多次所以自己机器上一直留着一份jdk-17_windows-x64_bin.zip版本号锁死在 17.0.3.1。JDK 17 是 Java SE 的长期支持版本按 Oracle 免费条款和条件许可这个二进制包在生产环境可以免费使用、也能免费再分发对中小团队来说省掉了授权层面的顾虑。这份 zip 是 Windows x64 平台的完整 JDK解压即用不需要安装器写注册表特别适合需要多版本共存、或者 CI 机器上要临时切版本的场景。如果你也在维护 Java 项目、经常被版本问题绊住这份东西值得放在手边。2. 解压前先看清目录jdk-17.0.3.1 里到底装了什么很多人拿到 zip 直接双击解压然后bin目录一加就完事其实这个包里的结构值得先扫一遍。理解每个目录干什么后面配环境变量、排查类加载问题会省很多事。2.1 bin、conf、lib、jmods 四个核心目录的分工解压jdk-17_windows-x64_bin.zip之后根目录下会看到bin、conf、include、jmods、legal、lib这几个文件夹。bin里是可执行文件java.exe、javac.exe、jar.exe、jlink.exe都在这里日常敲命令靠它。conf是 JDK 17 才独立出来的配置目录net.properties、security子目录、jaxp.properties都在这以前这些散在lib里现在拆开更清晰。lib放的是运行时依赖modules文件那个几百 MB 的大文件就在这JVM 启动时按需加载。jmods是模块化之后的.jmod文件做自定义运行时镜像jlink时会用到。include是给 JNI 开发用的 C 头文件纯 Java 项目可以忽略。这里有个容易忽略的点conf/security/java.security这个文件控制着安全提供者和算法策略后面讲 TLS 握手失败时会回到它。lib/modules不要手动去改它是打包好的模块镜像改了 JVM 直接起不来。2.2 版本号里的 0.3.1 意味着什么17.0.3.1拆开看17是大版本0是次要版本3是安全补丁号最后那个.1是补丁的补丁。Java 的版本节奏是每季度发一次补丁.3对应的是某个季度的安全更新.1是在此基础上的紧急修复。选 17.0.3.1 而不是 17.0.3通常是因为前者修了某个具体缺陷。生产环境锁版本时我一般会记下完整四段号而不是只写 17因为不同补丁之间行为可能有细微差别尤其是涉及 TLS、时区、字符集的修复。2.3 和 JRE 的关系为什么现在只发 JDK从 JDK 9 开始Oracle 就不再单独发 JRE 了JDK 里已经包含完整的运行时。JDK 17 同样如此bin目录里既有编译工具也有运行工具。如果你只需要跑 Java 程序用jlink裁一个精简运行时出来就行没必要再去找独立的 JRE 包。这也是为什么现在下载页面上只有 JDK 的 zip没有单独的 JRE zip。3. 从 zip 到能跑Windows 下的解压、环境变量与验证这一章是实打实的操作。我按自己在新机器上配环境的顺序写每一步都有对应的命令和验证方式照着走一遍基本不会翻车。3.1 解压位置的选择与目录命名不要解压到C:\Program Files下面那个路径有空格某些老构建脚本处理不好带空格的JAVA_HOME。我一般放在D:\dev\jdk\下面目录名带上完整版本号方便多版本共存# 假设 zip 下载在 D:\downloads\ # 用 PowerShell 解压Windows 10 以上自带 Expand-Archive Expand-Archive -Path D:\downloads\jdk-17_windows-x64_bin.zip -DestinationPath D:\dev\jdk\ # 解压后会得到一个 jdk-17.0.3.1 目录 # 确认目录结构 dir D:\dev\jdk\jdk-17.0.3.1Expand-Archive是 PowerShell 内置命令不用装 7-Zip 也能解。解压完确认一下bin\java.exe存在如果解压出来是嵌套两层同名目录手动把内层挪出来保持D:\dev\jdk\jdk-17.0.3.1\bin\java.exe这个层级。3.2 JAVA_HOME 与 Path 的正确配法环境变量配错是新手最常见的翻车点。JAVA_HOME指向 JDK 根目录不是binPath里加的是%JAVA_HOME%\bin不是直接写死路径。这样以后换版本只改JAVA_HOME一处。# 用 setx 设置用户级环境变量需要重开终端生效 setx JAVA_HOME D:\dev\jdk\jdk-17.0.3.1 # 把 %JAVA_HOME%\bin 追加到 Path # 注意setx 会覆盖原有 Path先读出来再拼避免误删 for /f tokens2* %a in (reg query HKCU\Environment /v Path 2^nul) do set OLDPATH%b setx Path %OLDPATH%;%JAVA_HOME%\binsetx写的是注册表里的用户环境变量当前终端不会立即生效要新开一个 cmd 或 PowerShell。for /f那行是从注册表读旧 Path防止setx直接覆盖导致原有路径丢失——这个坑我踩过Path 被清空后一堆命令找不到。如果你不放心命令行直接去「系统属性 → 环境变量」图形界面改也行效果一样。3.3 验证安装java -version 与 javac -version 都要看配完环境变量新开终端跑两条命令java -version # 期望输出 # java version 17.0.3.1 2022-04-22 LTS # Java(TM) SE Runtime Environment (build 17.0.3.12-LTS-6) # Java HotSpot(TM) 64-Bit Server VM (build 17.0.3.12-LTS-6, mixed mode, sharing) javac -version # 期望输出javac 17.0.3.1两条都要看。只跑java -version有可能命中的是系统里另一个旧版本javac -version能确认编译器也是 17。如果java能跑但javac报「不是内部或外部命令」说明Path没配对回去检查%JAVA_HOME%\bin是否真的加进去了。输出里的64-Bit确认你用的是 x64 版本和下载的windows-x64_bin.zip对得上。3.4 写一个最小程序验证编译与运行链路光看版本号还不够跑一个带新特性的小程序确认编译和运行都正常// HelloRecord.java // 用 record 类型验证 JDK 17 的编译与运行 public class HelloRecord { record Point(int x, int y) {} public static void main(String[] args) { Point p new Point(3, 4); // 文本块是 JDK 15 引入的特性17 已正式支持 String msg Point: %s Distance squared: %d .formatted(p, p.x() * p.x() p.y() * p.y()); System.out.print(msg); } }javac HelloRecord.java java HelloRecord # 期望输出 # Point: Point[x3, y4] # Distance squared: 25record是 JDK 16 转正、17 稳定支持的语法文本块在 15 转正。这段代码同时用到了两个 17 的特性能跑通说明编译器和运行时都是 17 级别。如果javac报「record 是预览特性」说明你实际用的不是 17回去查javac -version。4. 多版本共存与构建工具对接别让 JAVA_HOME 打架实际开发中很少只装一个 JDK。老项目要 8新项目要 17机器上同时存在两三个版本是常态。这一章讲怎么让它们和平共处以及 Maven、Gradle 怎么正确识别。4.1 用目录命名区分版本靠切换 JAVA_HOME 换版本我的做法是D:\dev\jdk\下面放多个目录jdk-8u301、jdk-11.0.12、jdk-17.0.3.1。切换版本时只改JAVA_HOME指向哪个目录Path里始终是%JAVA_HOME%\bin。这样不用反复改 Path也不会出现两个版本的java.exe同时出现在 Path 里导致命中顺序混乱。# 切到 17 setx JAVA_HOME D:\dev\jdk\jdk-17.0.3.1 # 切到 8 setx JAVA_HOME D:\dev\jdk\jdk-8u301每次改完要新开终端。如果嫌麻烦可以写两个.bat脚本双击就切本质还是改JAVA_HOME。注意setx有长度限制1024 字符Path 特别长的时候要留意。4.2 Maven 的 toolchains 与 maven.compiler.releaseMaven 默认用JAVA_HOME指向的 JDK 编译。如果项目要求用 17 编译但你的JAVA_HOME是 8可以在pom.xml里指定properties !-- 指定编译目标版本release 比 source/target 更严格 -- maven.compiler.release17/maven.compiler.release project.build.sourceEncodingUTF-8/project.build.sourceEncoding /propertiesmaven.compiler.release是 JDK 9 之后推荐的写法它会同时约束source、target和bootclasspath避免用高版本 JDK 编译出低版本字节码时误引用新 API。如果团队里 JDK 版本不统一更规范的做法是配toolchains.xml让 Maven 按项目要求自动选 JDK而不是依赖JAVA_HOME。toolchains.xml放在~/.m2/下里面声明每个 JDK 的路径和版本pom.xml里用maven-toolchains-plugin绑定。4.3 Gradle 的 java.toolchain 配置Gradle 6.7 之后引入了 toolchain 概念比 Maven 的 toolchains 更顺手// build.gradle java { toolchain { // 声明用 JDK 17 编译和运行Gradle 会自动找匹配的 JDK languageVersion JavaLanguageVersion.of(17) } }配了 toolchain 之后Gradle 会自己去常见安装路径找 JDK 17找不到才报错。它不会受JAVA_HOME影响这对 CI 环境特别友好——CI 机器上JAVA_HOME可能是任意版本但项目声明了 17Gradle 就会用 17。前提是机器上确实装了 17或者开了自动下载org.gradle.java.installations.auto-downloadtrue。4.4 IDE 里的 SDK 配置别漏掉命令行配好了IDE 里还要单独设。IntelliJ IDEA 里File → Project Structure → SDKs添加D:\dev\jdk\jdk-17.0.3.1然后在Project里把 language level 设成 17。Eclipse 在Preferences → Java → Installed JREs里加。IDE 不读系统JAVA_HOME它有自己的配置这一步漏了会出现「命令行能编译、IDE 里报错」的诡异现象。5. 避坑与排查jdk-17.0.3.1 在 Windows 上的五个真实翻车记录这一章全是我自己或身边人踩过的坑按「现象 → 原因 → 解决」写。遇到问题先对照这里能省不少搜索时间。5.1 现象java -version 显示 1.8明明 JAVA_HOME 已经改成 17原因Path 里存在多个 java.exe且旧版本的路径排在前面。Windows 按 Path 顺序查找先命中的先执行。常见于以前装过 JDK 8 且安装器往C:\ProgramData\Oracle\Java\javapath写了软链接。解决把%JAVA_HOME%\bin移到 Path 最前面或者删掉C:\ProgramData\Oracle\Java\javapath和C:\Windows\System32下的java.exe后者是安装器放的删之前确认没有其他程序依赖。改完新开终端再验证。5.2 现象解压后运行 java 报「无法定位程序输入点 xxx 于动态链接库」原因zip 解压不完整或者被杀毒软件拦截了部分文件。bin目录下的 DLL 和lib里的文件缺一不可。解决重新解压解压前暂时关闭实时防护解压后核对bin目录下java.exe、javaw.exe、server\jvm.dll是否都在。用Expand-Archive解压比某些第三方工具更可靠不会漏文件。5.3 现象编译时报「错误: 不支持发行版本 17」原因javac实际用的不是 17或者构建工具里source/target配成了别的版本。Maven 项目里如果pom.xml没配maven.compiler.release会默认用插件的旧默认值。解决先javac -version确认编译器版本。Maven 项目检查pom.xml的maven-compiler-plugin配置显式写release17/release。Gradle 项目检查sourceCompatibility和targetCompatibility或者直接用 toolchain。5.4 现象程序运行时报「no fontconfig.bfc found」或字体相关警告原因JDK 在 Windows 上依赖系统字体lib目录下的fontconfig.bfc是字体配置缓存。如果这个文件损坏或缺失AWT/Swing 程序会报字体警告严重时界面渲染异常。解决从原始 zip 里重新提取lib\fontconfig.bfc覆盖过去。不要手动编辑这个文件它是二进制格式。如果只是警告不影响功能可以忽略如果界面出问题换回完整解压的版本。5.5 现象TLS 握手失败报「unable to find valid certification path」原因cacerts信任库里的根证书过期或缺失或者conf/security/java.security里的安全策略被改过。JDK 17 的cacerts默认密码是changeit但一般不需要动它。解决先确认lib\security\cacerts文件存在且大小正常约 100 多 KB。如果怀疑证书问题用keytool -list -cacerts查看信任库内容。企业内网自签证书的场景需要用keytool -importcert把企业根证书导进去而不是去改java.security关掉校验——关校验是饮鸩止渴生产环境绝对不能这么干。6. 用 jlink 裁一个 40MB 的运行时把 jdk-17.0.3.1 用出花JDK 17 的模块化让裁剪运行时变得很实际。一个完整 JDK 解压后 300MB 左右但如果你只是部署一个 Spring Boot 服务用jlink裁出来的运行时可以压到 4060MB镜像体积直接降一个量级。这一章讲怎么裁、怎么验证、以及我踩过的模块缺失坑。先确认你的应用依赖哪些模块。最省事的办法是用jdeps分析# 分析一个 jar 的模块依赖 jdeps --multi-release 17 --ignore-missing-deps --print-module-deps your-app.jar # 输出类似java.base,java.logging,java.sql,java.naming--print-module-deps会列出运行这个 jar 所需的最小模块集。--ignore-missing-deps是防止某些可选依赖缺失导致分析中断。拿到模块列表后用jlink生成运行时# 生成自定义运行时镜像到 D:\dev\jre-mini jlink ^ --add-modules java.base,java.logging,java.sql,java.naming ^ --output D:\dev\jre-mini ^ --strip-debug ^ --no-header-files ^ --no-man-pages ^ --compress2参数逐个说--add-modules是要包含的模块--output是输出目录--strip-debug去掉调试信息--no-header-files去掉 JNI 头文件--no-man-pages去掉手册页--compress2是压缩级别0 不压缩1 常量字符串共享2 更激进。裁完的目录里同样有bin\java.exe可以直接当 JRE 用。验证裁出来的运行时能不能跑你的应用D:\dev\jre-mini\bin\java -jar your-app.jar如果报NoClassDefFoundError或module not found说明模块漏了。常见漏网之鱼是java.desktop用到 AWT/Swing 时、jdk.crypto.ecTLS 椭圆曲线加密、java.xml解析 XML 配置时。补上对应模块重新jlink即可。我一般会先用完整 JDK 跑一遍应用确认功能正常再裁运行时这样能把「应用本身的问题」和「模块缺失的问题」分开。还有一个坑jlink生成的运行时不能跨平台。你在 Windows 上裁出来的只能给 Windows 用Linux 镜像要在 Linux 上裁或者用--module-path指向对应平台的 jmods。Docker 多阶段构建里常见做法是在构建阶段用完整 JDK 裁运行时再把裁好的目录复制到最终镜像。从那以后我每次部署新服务都会先跑一遍jdeps确认模块列表再jlink裁运行时最后用裁出来的java跑一遍冒烟测试才敢上镜像。这套流程走顺了镜像体积和启动速度都能明显改善。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?