简介这是一份面向 Java 开发者、学生和运维人员的 JDK 15.0.2 官方压缩安装包专门用于离线部署、手动配置环境变量或在受限网络中搭建 Java 开发环境同时适合学习 Switch 表达式、文本块、Records 等最新语言特性。压缩包共三百八十四个文件大小约 179.66MB核心内容包括 jmod 模块文件、so 动态链接库、h 原生头文件、jar 工具包以及 javac、java、jshell 等命令行程序能够完整支撑编译、运行、调试和模块化部署。这一版本进一步降低 ZGC 与 Shenandoah GC 的暂停时间默认采用 UTF-8 源码编码正式弃用 Applet API并引入文本块、记录类等简化代码的特性适合做性能对比和新特性验证。目前已有三百八十七人浏览学习说明该版本在离线适配、旧系统兼容和特定工具链依赖方面仍有较高的关注度。通过这份资源读者可一次性获得完整 JDK 15.0.2 组件无需联网即可搭建 Java 实验环境、复现兼容性问题或深入分析 JDK 内部结构缩短环境准备时间聚焦业务开发与技术研究。1. 拿到的这个 jdk15.0.2.zip到底能帮你解决什么如果你手里正拿着一个 jdk15.0.2.zip 的文件大概率是刚从某个下载页把它拖下来准备装进系统跑一个 Java 项目。这个压缩包解出来就是完整的 JDK 15.0.2对应的是 OpenJDK 针对 15 版本发布的第二次安全修复更新也是 15 这个短期支持版本最后一批能用的补丁之一。它本身不是大版本但修复了一批安全问题还顺带把 15 里的几个新特性运行时的坑给补上了。这篇文章就是给你把这套东西拆开15.0.2 这个版本号在 Java 发布体系里处于什么位置zip 解压后环境变量怎么配最快跑起来怎么用 jshell 和 javac 验证工具链没装错以及装完之后最容易踩的几个坑。适合刚下载还没动手装的开发者也适合那些明明装了却说 Java 版本不对、项目编译报错的熟手对照着排一遍。整个过程一条命令一条命令来可复现。2. 为什么 15.0.2 值得装版本号里的信息和语言层面的变化2.1 版本号拆解15、0、2 分别代表什么Java 从 2017 年开始切到六个月一个大版本的节奏版本号的语义和以前 J2SE 1.4 那种完全不一样了。15.0.2 里的 15 是功能版本号也就是 2020 年 9 月发布的 Java 15中间那个 0 在 Oracle 的版本命名规范里原本叫月份版本号但在新的时间驱动模型里其实已经不再承担太多语义基本固定是 0最后的 2 是补丁版本号表示这是 15 的第二个安全更新。这个命名规则的实用意义在于看到 15.0.2 你就该意识到这个版本是“15 两个补丁”而不是“比 15 大一个小版本”。它不会给你带来新的语言特性但会包含一批安全修复和 bug fix。如果你当前用的是 15.0.1 甚至 15.0.0升级到 15.0.2 属于典型的“同功能版本内打补丁”风险极小收益是实打实的安全加固。另一个值得注意的点是15 本身是短期支持版本。按照 OpenJDK 的支持策略15 的社区支持在 2021 年 3 月就结束了后面不会再出免费的 15.0.3。也就是说 15.0.2 基本是 15 这条路线的终点了。如果项目能接受直接上 17 会拿到更长的支持周期但如果你因为某些依赖还没法升到高版本15.0.2 就是 15 系列的最优解比停留在 15.0.0 稳妥得多。2.2 文本块转正和密封类预览两个值得动手试一试的语言级改动15 这个版本最值得关注的语言特性一是文本块Text Blocks从预览转正二是密封类Sealed Classes以预览形态首次亮相。文本块的核心价值在于你终于可以用三引号写多行字符串不用再在 Java 代码里拼一堆 \n 和加号了处理 JSON、HTML 模板这类场景可读性提升非常明显。从 15 开始这个特性不需要任何编译参数直接就能用。密封类解决的是继承控制问题。用 sealed 修饰一个类或者接口然后用 permits 明确列出允许继承它的子类其他类一律不允许再继承。这在领域建模里特别实用比如一个业务状态机状态就那么几种用密封类把可能性锁死写 switch 的时候编译器也能帮你穷尽分支。不过 15 里它还是预览特性用的时候编译和运行都要加 --enable-preview这一点很容易踩坑后面专门讲。对正在从 Java 8 往上升级的人来说文本块是立刻能提升日常编码效率的特性密封类则需要等到 17 正式转正后再放心引入生产环境在 15 上可以作为学习用途试一试不建议写进核心业务代码。这个取舍本身也体现了短期支持版本的使用策略尝鲜可以上生产要等 LTS。2.3 垃圾收集器变化ZGC 和 Shenandoah 都转正了15 在 JVM 层面有个容易被忽略但影响深远的变化ZGC 和 Shenandoah 两个低延迟垃圾收集器都从实验状态转正了。ZGC 从 11 开始引入实验版本到 15 的 JEP 377 正式转正不再需要 -XX:UnlockExperimentalVMOptions 这个前置开关直接用 -XX:UseZGC 就能启用。Shenandoah 也是类似JEP 379 把它从实验状态放了出来。这对做服务端应用的人意味着什么以前为了压 GC 停顿时间要么上 G1 然后调一堆参数要么担惊受怕地用实验开关开 ZGC。现在 15 上可以直接在生产环境启用 ZGC特别是堆内存到了几十 GB 的场景ZGC 能把停顿时间控制在毫秒级对响应时间敏感的服务收益很明显。我用 -XX:UseZGC 跑过一个模拟项目X的压测GC 停顿从 G1 的几十毫秒降到了个位数毫秒。验证你装的 JDK 15.0.2 支不支持这些特性不需要真的写代码直接查 JVM 参数就行java -XX:UseZGC -version java -XX:PrintFlagsFinal -version | grep UseZGC第一条命令如果正常输出版本信息说明 ZGC 可用第二条会打印 UseZGC 的最终布尔值。如果某个特性没转正启动时通常会直接报 Unrecognized VM option这种直观报错反而比查文档来得快。从 15 开始G1 仍然是默认收集器ZGC 是有明确低延迟诉求时才切换的选项。2.4 这版也删了一些东西CMS 正式移除的连带影响如果说加特性是往前看那删东西就是算旧账。15 里正式把 CMS 垃圾收集器从源码里移除干净了JEP 363 执行这个动作。如果哪个老项目的启动参数里还写着 -XX:UseConcMarkSweepGC在 15.0.2 上会直接启动失败报 VM option 不识别。这是从 14 开始的移除过程到 15 彻底落地。删除的另一个重点是 Nashorn JavaScript 引擎JEP 372 把它也移除了。以前在 Java 里调 js 脚本的场景在 15 上默认引擎已经没了。项目里如果依赖 javax.script 调 Nashorn升到 15 之前得先确认是不是还有别的替代引擎否则运行时会遇到 ScriptEngine 找不到的报错。这种删除对升级决策的影响比新增特性大。新增特性你不用不影响删除的东西如果你在用那就是硬冲突。所以在决定装 15.0.2 之前建议先扫一遍启动脚本和代码里有没有 CMS 和 Nashorn 相关引用有就得先换掉再升。这也是为什么我一般建议项目从 8 往上升级时先定一个中间目标版本15 适合做过渡验证但真正要长期待的地方是后续的 LTS 版本。3. 解压 jdk15.0.2.zip 到跑通 java -version最小安装步骤与参数说明3.1 Windows 环境解压目录规划和两个核心环境变量拿到 jdk15.0.2.zip 之后第一步是把它放到一个路径稳定、没有空格和中文的目录里。这里说的“路径稳定”是指不要在 C 盘临时目录里解压了就用因为后面 JAVA_HOME 和 PATH 都要指向这个位置目录一旦挪动所有依赖它的工具都会跟着失效。我一般会在 D 盘或者 C 盘根目录建一个 dev 文件夹专门放开发工具链。解压这一步不需要额外的解压软件Windows 10 及以后的系统自带的 tar 命令就能处理 zip 格式。在 PowerShell 或 CMD 里切到目标目录后执行cd C:\dev tar -xzf C:\Users\你的账号\Downloads\jdk15.0.2.zip解压完成后确认一下目录结构。正常情况下你会看到 C:\dev\jdk-15.0.2 这个文件夹里面直接就是 bin、conf、lib 这些子目录。如果你解压出来发现多了一层嵌套目录比如 C:\dev\jdk-15.0.2\jdk-15.0.2那说明你的解压方式可能创建了多余的一层后面配 JAVA_HOME 的时候指对层级就行不需要重新解压。接下来配环境变量。JAVA_HOME 指向 JDK 的解压根目录PATH 里加上 bin 目录。注意命令行临时设置和系统级持久设置是两回事我建议直接用系统设置界面操作避免 setx 带来的副作用。在 Windows 搜索“环境变量”打开“编辑系统环境变量”然后新建 JAVA_HOMEJAVA_HOMEC:\dev\jdk-15.0.2然后在系统变量的 Path 里新增一行%JAVA_HOME%\bin3.2 为什么 JAVA_HOME 要单独设而不是只改 PATH很多新手会想既然 PATH 里已经有 bin 目录了java 命令就能用了为什么还要多此一举设一个 JAVA_HOME这个问题的答案要看你后面的工具链。Maven、Gradle、IDEA 这些工具在找 JDK 的时候第一优先读取的就是 JAVA_HOME 环境变量而不是去 PATH 里猜。PATH 只负责让你在命令行里能敲出 java 这个命令JAVA_HOME 是让整个 Java 生态的工具都能定位到这个 JDK。所以这两者都要配而且 JAVA_HOME 必须指到 JDK 的根目录不是 bin 目录。有一个常见的低级错误是把 JAVA_HOME 指成了 C:\dev\jdk-15.0.2\bin结果 java 命令能执行但 Maven 启动直接报错因为 Maven 会在 JAVA_HOME 下找 lib 目录和 jre 目录指到 bin 下面自然什么都找不到。这个路径层级问题值得在配的时候就确认清楚。PATH 里加 %JAVA_HOME%\bin 而不是直接写 C:\dev\jdk-15.0.2\bin好处是以后升级 JDK 只改 JAVA_HOME 一个变量PATH 不用动。如果你同时装了多个 JDK这个习惯能省掉很多切换版本时的混乱。环境变量配好之后新开的命令行窗口才会加载新值已经打开的窗口里 java 命令还是旧状态这个现象不是配置失败是进程环境继承机制决定的。3.3 Linux 和 macOS 环境的对应操作如果 jdk15.0.2.zip 是在 Linux 服务器上解压操作逻辑完全一样只是工具链换一下。Linux 下一般下载的是 .tar.gz 包但如果你手头只有 zip用 unzip 命令也能解。先确认 unzip 有没有装没装的话用发行版的包管理器装一个然后执行sudo mkdir -p /opt/jdk sudo unzip jdk15.0.2.zip -d /opt/jdk export JAVA_HOME/opt/jdk/jdk-15.0.2 export PATH$JAVA_HOME/bin:$PATH这里的 export 只在当前终端会话有效关掉终端就没了。要持久化把下面两行写进 ~/.bashrc 或者 ~/.zshrc 里export JAVA_HOME/opt/jdk/jdk-15.0.2 export PATH$JAVA_HOME/bin:$PATH写完执行 source ~/.bashrc 让配置立即生效。macOS 用户如果是 zsh改 ~/.zshrc 即可。这个套路和 Windows 的差异只在语法层面核心还是 JAVA_HOME 指根目录、PATH 追加 bin 目录这两个不变的原则。3.4 验证安装java -version 的输出怎么看配置完成并新开一个终端窗口后先跑 java -version 看结果。正常的输出长这样openjdk version 15.0.2 2021-01-19 OpenJDK Runtime Environment (build 15.0.2xx-xxx) OpenJDK 64-Bit Server VM (build 15.0.2xx-xxx, mixed mode, sharing)第一行里的 openjdk version 15.0.2 是关键确认版本号没配错。如果这里显示的是 1.8.0 或者 11.0.x说明你的 PATH 里有旧版本的 JDK 排在前面新配置没生效。这时候用 where java 查一下实际执行的是哪个路径大概率会发现系统目录下有个更老的 java.exe 在抢先。解决方法是把 %JAVA_HOME%\bin 移到 Path 列表的最前面或者把 C:\Windows\System32 里那个 java.exe 的处理优先级降下来。输出里的 mixed mode 表示 JVM 以解释器和 JIT 编译器混合模式运行这是正常状态不用疑虑。sharing 表示类数据共享开启也是默认行为。看到这四行输出后顺手再敲一条 javac -version确认编译器版本和 java 一致。有些环境只把 JDK 的 bin 加进了 PATH但 JAVA_HOME 配错或者没配导致 java 能用 javac 找不到两个版本对不上这是后面编译期各种诡异报错的源头之一。4. 用 jshell 和 javac 验证工具链从 Hello 到密封类的编译实战4.1 jshell装完环境后的第一行 Java 代码环境变量配好之后第一个要验证的是交互式编程工具 jshell。它是 JDK 9 开始自带的 REPL 工具对验证环境是否真正可用来说比写一个完整的类文件效率高很多。在命令行直接敲 jshell 进入交互界面jshell进入后你会看到类似 jshell 的提示符。在里面输入下面这行代码验证解释器能正常执行System.out.println(jdk15.0.2 running);正常会立刻打印出 jdk15.0.2 running。这一步看着简单但能同时证明两件事JAVA_HOME 指向的 JDK 能启动 Java 虚拟机类加载和基础库都没问题。如果这一步报错比如提示找不到 jshell 命令那基本可以确定 PATH 配置有问题回到上一章排查路径。jshell 还能用来快速验证一些语言特性。比如想确认文本块在当前环境是否可用直接输入多行字符串的写法看输出是否符合预期。这个验证方式不需要创建任何文件特别适合刚装完环境时做冒烟测试。退出用 /exit 命令或者 CtrlD 快捷键。4.2 用文本块写一个可编译的 Java 文件jshell 验证通过后再从交互式环境走出来用一个完整的 Java 文件验证 javac 编译链路。这也是从“环境能跑”到“项目能编”之间必经的一步。新建一个 Hello.java写入用文本块特性的代码public class Hello { public static void main(String[] args) { String json { name: jdk15.0.2, status: ok } ; System.out.println(json); } }这段代码的核心是 包裹的多行字符串文本块会保留换行和缩进结构省掉了以前写 \n 和加号拼接的繁琐。注意文本块的第一行换行会被自动去掉所以最左边的大括号位置取决于你的代码缩进这个规则和 Python 的多行字符串有些类似但只针对字符串字面量不影响代码结构。然后在命令行执行编译和运行javac -d out Hello.java java -cp out Hello-d out 指定编译输出目录避免 .class 文件和源码混在一起-cp out 告诉运行时去 out 目录找类。输出应该是保留了三行结构的 JSON 文本。整个链路走通说明 javac 和 java 都正常工作且版本一致。4.3 编译一个带密封类的程序顺便认识 --enable-preview文本块在 15 里已经转正可以直接用但密封类在 15 里是预览特性编译时不给特殊参数会直接报错。写一个显式展示这个过程的例子先创建一个 Shape.java用 sealed 修饰接口sealed interface Shape permits Circle, Rectangle {} record Circle(double radius) implements Shape {} record Rectangle(double width, double height) implements Shape {} public class Main { public static void main(String[] args) { Shape shape new Circle(1.5); System.out.println(shape); } }这里同时用到了密封类接口和 record两个都是预览特性。直接编译会得到类似“错误: 预览功能未启用”的报错原因是 JVM 出于兼容性考虑默认关闭了所有预览特性。解决方式是在 javac 命令里显式启用javac --enable-preview --release 15 -d out Shape.java Main.java java --enable-preview -cp out Main注意两个关键点编译加了 --enable-preview 之后运行时也必须加否则会报“类文件具有错误的版本”或者找不到某些类的错误。另外 --release 15 这个参数要和 --enable-preview 同时出现如果你写的是 --source 15 而不是 --release 15有时候会收到提示要求统一。这是我遇到的比较常见的参数组合坑。4.4 控制字节码版本javac 的 --release 到底管什么--release 这个参数值得单独说清楚。它一次性控制了三个维度源码接受的语法版本、编译产出的字节码版本、以及编译时引用的 JDK API 集合。也就是说用 --release 15 编译出来的 class 文件可以在任何支持 Java 15 的 JVM 上运行而不是只能在 JDK 15.0.2 上运行。如果不用 --releasejavac 默认按当前 JDK 的版本编译产出的是 15 版本的字节码。这在一个开发机装了多个 JDK 的环境里容易出问题你用 JDK 17 的 javac 编译不加 --release产出的 class 文件是 17 版本的部署到只有 15 的服务器上直接抛 UnsupportedClassVersionError。所以我建议编译脚本里固定写 --release 15让构建结果和运行环境解耦不依赖本机 javac 的默认行为。验证 --release 是否生效可以用 javap 查看 class 文件的字节码主版本号javap -v Hello.class | grep major主版本 59 对应 Java 15。这个数字记法是有规律的Java 8 是 52之后每个版本加 1所以 15 就是 59。以后看到 UnsupportedClassVersionError 报错就能自己用这个命令快速确认 class 文件到底是哪个版本编出来的不用靠猜。5. 安装与切换 JDK 15.0.2 的常见问题5 个踩坑记录与排查方法5.1 java -version 显示旧版本新装的 15.0.2 没生效**现象**配置完 JAVA_HOME 和 PATH 后打开新终端执行 java -version显示的仍然是 1.8.0_xxx 或者 11.0.x看起来新装的 JDK 15.0.2 完全没被系统识别到。**原因**这是 PATH 里的命令查找顺序问题。系统在执行 java 命令时会按 PATH 里列出的目录顺序从上到下找第一个匹配的 java.exe。Windows 的 C:\Windows\System32 目录里经常会存在一个 java.exe它是某些软件安装时自动塞进去的排在你的 %JAVA_HOME%\bin 前面所以系统永远先命中它。**解决**先用 where java 列出所有匹配的 java.exe 路径确认到底在执行哪个。然后在环境变量编辑界面里把 %JAVA_HOME%\bin 这一项通过“上移”按钮挪到 Path 列表的最顶部。改完重新开终端验证如果仍然不对检查是不是有脚本在启动终端时覆盖了 PATH 环境变量。5.2 JAVA_HOME 指错层级Maven 和 IDEA 都找不到 JDK**现象**命令行里 java -version 完全正常但启动 Maven 报错提示找不到 JRE 或者无法定位 JDKIDEA 里添加 JDK 时选了解压目录也报不是有效的 JDK 路径。**原因**JAVA_HOME 指向了解压后的内层目录或者是把 bin 目录加了进去。JAVA_HOME 的正确层级必须是 JDK 的根目录也就是直接包含 bin、lib、conf 那一层的文件夹。如果你解压出来的结构是 jdk-15.0.2 里面又套了一层 jdk-15.0.2把外层的根目录指给 JAVA_HOME工具会到根目录下找 bin但实际 bin 在内层的目录里自然找不到。**解决**先执行 echo %JAVA_HOME% 确认当前值再去磁盘上看实际的目录层级确保 JAVA_HOME 指到直接包含 bin 目录的那个文件夹。另外IDEA 里添加 JDK 时选择目录要选到 bin 的上一层IDEA 会自己识别目录下的 release 文件来确认版本号不需要你手动填写版本信息。5.3 预览特性编译报错提示需要开启 --enable-preview**现象**用 sealed 或者 record 写代码javac 编译时报“错误: 预览功能未启用请使用 --enable-preview 以启用预览功能”看起来编译器和源码都没问题但就是不让你过。**原因**预览特性的设计初衷是收集反馈不保证未来版本兼容所以 JVM 默认完全关闭它们。你必须在编译和运行两个阶段都显式开启少一个都会报错。很多人在编译时加了 --enable-preview运行时忘了加结果启动 Java 程序时又报 ClassFormatError 或者 UnsupportedClassVersionError还会怀疑是 --release 版本配错了。**解决**把编译和运行两条命令写在一起保持参数一致。编译时用 javac --enable-preview --release 15运行时用 java --enable-preview。另外注意预览特性在编译时加了 --release 之后不能再额外指定 --source 或 --target这三个参数是互斥关系写法要统一。5.4 Maven 编译时提示无效的目标版本15**现象**项目在 pom.xml 里配了 maven.compiler.source 和 maven.compiler.target 为 15执行 mvn compile 时报“无效的目标发行版: 15”或者“不受支持的类文件主要版本号 59”但本机 java -version 明明已经显示 15.0.2。**原因**Maven 默认使用的编译器插件版本太老不识别 15 这个版本号。Maven 编译过程不是直接调用命令行 javac而是通过 maven-compiler-plugin 来驱动插件有它自己支持的 Java 版本上限。老版本插件遇到新版本号要么直接报不认识要么编译出旧版本的字节码导致后续运行时不匹配。**解决**在 pom.xml 的 build 节点里显式指定 maven-compiler-plugin 的新版本号并且用 release 参数替代 source 和 target这样更符合新版编译逻辑build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.13.0/version configuration release15/release /configuration /plugin /plugins /build这里用的 3.13.0 是当前比较稳妥的版本号能正常识别 15 及以上的 Java 版本。改完 pom 之后重新执行 mvn clean compile如果还报错顺手跑一下 mvn -version 看 Maven 本身使用的 Java 版本Maven 的运行 JVM 和编译目标版本是两回事别搞混。5.5 IDEA 里启动项目报模块读取错误提示类文件版本不对**现象**IDEA 里配置好了 JDK 15.0.2项目也能正常编译但运行时抛异常报“java.lang.UnsupportedClassVersionError”或者“模块读取错误: 类文件具有错误的版本”实际错误信息里的数字比如 59.0。**原因**问题通常出在依赖的 jar 包。有些项目依赖还是用旧 JDK 编译的比如 Java 8 编译产出的 class 文件版本是 52在 Java 15 上运行完全没问题反过来说如果某个依赖是用 JDK 17 编译的主版本号 61 的 class 文件放在 JDK 15.0.2 的环境里跑JVM 会直接拒绝。另一个常见原因是 IDEA 的 Project SDK 和 Modules 的 language level 设置不一致两个地方版本对不上。**解决**在 File → Project Structure 里同时检查 Project SDK 和 Modules 的 language level确保两者都是 15。然后对依赖 jar 做一个排查把报错的 jar 找出来用 javap -v 看它的 major version高于 59 的 jar 不能被 JDK 15 使用需要换对应版本。这是跨版本升级时最典型的依赖冲突排查思路就是版本号一层层查定位到具体是哪个 jar 出的问题再决定升 JDK 还是降依赖版本。6. 多版本 JDK 共存版本切换脚本与一条指令的自检习惯生产环境很少只装一个 JDK。一台开发机上同时有 8、11、17 是常态但 15.0.2 这种短期版本也有它的场景比如验证某个依赖对 15 的兼容性或者跑一些只有 15 才方便测的特性。多版本共存的关键在于切换机制要简单可靠不能每次手动改环境变量那样迟早配错。我在 Windows 上习惯用 setx 把版本号写进变量名再用一个切换脚本统一管理setx JDK15_HOME C:\dev\jdk-15.0.2 setx JDK17_HOME C:\dev\jdk-17然后写一个 jdk.bat 放在固定目录并加入 PATHecho off setx JAVA_HOME %%JDK15_HOME%% set JAVA_HOME%JDK15_HOME% set PATH%JAVA_HOME%\bin;%PATH% java -version脚本前两行做持久化中间的 set 让当前终端立即生效最后跑 java -version 告诉你现在指向哪个版本。虽然 setx 设置 JAVA_HOME 时用了延迟展开的写法但实际使用中这种脚本比手动改系统设置快得多。Linux 上对应的做法是 update-alternatives 或者直接改符号链接逻辑一样。另外有一个值得养成的自检习惯每次切完版本除了 java -version再把 javac -version 一起跑对比两个输出是否一致。好多环境问题都出在 java 和 javac 指向不同 JDKjava 能跑但编译用错版本。再配合前面讲过的 javap -v 查看 class 文件主版本号编译和运行两个环节的版本就都处于可验证状态了。JDK 15.0.2 这个版本到底值不值得装取决于你的具体处境如果只是想快速验证某个特性它完全够用如果要长期维护项目短期支持版本不是一个理想落点后续还是要往 LTS 版本走。但不管落在哪个版本把安装路径、环境变量、版本验证这三件事做扎实后面的路都会顺很多。这些操作里我踩过的坑远不止上面写的五条尤其是 IDEA 和 Maven 的版本不匹配问题配一次环境折腾掉一个下午很正常。希望这篇能帮你绕开这些弯路尽早把 15.0.2 用起来。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?