JDK 8、11、17、21 LTS 版本演进总览
JDK 8、11、17、21 是企业项目最常见的四条长期支持基线。学习版本特性不能只背“某版本增加了什么”,还要区分:特性在哪个版本首次出现、到哪个版本正式可用、怎样写代码、升级后哪些默认行为变化、旧依赖为什么会失效。
一、四个版本如何定位
| 版本 | 发布时间 | 企业定位 | 最应该掌握的主线 |
|---|---|---|---|
| JDK 8 | 2014 | 大量存量系统基线 | Lambda、Stream、java.time、CompletableFuture、集合与JVM变化 |
| JDK 11 | 2018 | 第一代模块化后的LTS | 标准HTTP Client、字符串/文件API、单文件运行、JPMS与移除模块 |
| JDK 17 | 2021 | Spring Boot 3最低基线、现代主流LTS | Record、密封类、文本块、Switch表达式、强封装、统一日志 |
| JDK 21 | 2023 | 新项目高并发与现代语言能力基线 | 虚拟线程、Record模式、Switch模式匹配、有序集合、分代ZGC |
“LTS”表示供应商通常提供更长维护周期,不表示其他版本没有新特性,也不表示所有发行版支持期限相同。生产选型要同时确认 JDK 发行商、框架基线、商业支持和补丁策略。
二、版本演进地图
flowchart LR
A["JDK 8<br/>函数式与现代API"] --> B["JDK 9~11<br/>模块化与工程增强"]
B --> C["JDK 12~17<br/>数据建模与语法成熟"]
C --> D["JDK 18~21<br/>虚拟线程与模式匹配"]| 能力 | JDK 8 | JDK 11 | JDK 17 | JDK 21 |
|---|---|---|---|---|
| Lambda、Stream | 正式引入 | 可用 | 可用 | 可用 |
java.time | 正式引入 | 可用 | 可用 | 可用 |
| JPMS模块系统 | 无 | 可用 | 强封装更严格 | 可用 |
| 标准HTTP Client | 无 | 正式引入 | 可用 | 可用 |
局部变量var | 无 | 可用,来自JDK 10 | 可用 | 可用 |
| Switch表达式 | 无 | 无 | 可用,来自JDK 14 | 可用 |
| 文本块 | 无 | 无 | 可用,来自JDK 15 | 可用 |
| Record | 无 | 无 | 可用,来自JDK 16 | 可配合Record模式 |
instanceof模式 | 无 | 无 | 可用,来自JDK 16 | 可用 |
| 密封类 | 无 | 无 | 正式引入 | 可用 |
| 虚拟线程 | 无 | 无 | 无 | 正式引入 |
| Switch模式匹配 | 无 | 无 | 仅预览阶段 | JDK 21正式引入 |
| Record模式 | 无 | 无 | 无 | JDK 21正式引入 |
| Sequenced Collections | 无 | 无 | 无 | JDK 21正式引入 |
三、不要混淆“该版本新增”和“升级到该版本可用”
从 JDK 8 直接升级到 JDK 11 时,会同时获得 JDK 9、10、11 的所有正式能力。例如 JPMS 和集合工厂来自 JDK 9,var 来自 JDK 10,标准 HTTP Client 来自 JDK 11。面试回答应说清首次引入版本:
| 能力 | 首次正式版本 |
|---|---|
List.of、JPMS、JShell | JDK 9 |
局部变量var | JDK 10 |
| 标准HTTP Client、单文件源码运行 | JDK 11 |
| Switch表达式 | JDK 14 |
| 文本块 | JDK 15 |
Record、instanceof模式匹配 | JDK 16 |
| 密封类 | JDK 17 |
| 虚拟线程、Record模式、Switch模式匹配、Sequenced Collections | JDK 21 |
四、四个版本的详细学习入口
| 页面 | 内容 |
|---|---|
| JDK 8新增特性与实战 | Lambda、Stream、Optional、java.time、接口、并发、集合、JVM |
| JDK 11新增特性与实战 | 9~11累计能力、HTTP Client、字符串/文件API、JPMS、迁移风险 |
| JDK 17新增特性与实战 | 12~17累计能力、Record、密封类、文本块、强封装和运行时变化 |
| JDK 21新增特性与实战 | 18~21累计能力、虚拟线程、模式匹配、有序集合、分代ZGC |
五、编译版本、运行版本和API版本
| 概念 | 决定什么 | 检查方式 |
|---|---|---|
| 编译JDK | 实际执行哪个javac | mvn -v、gradle -version |
| Source | 允许使用什么语言语法 | 编译插件配置 |
| Target | 输出什么Class版本 | javap -verbose |
| Release | 同时限制语法、Class版本和标准库API | javac --release |
| 运行JDK | 哪个JVM真正执行程序 | java -version、进程命令行 |
只写source=8,target=8不等于真正兼容Java 8:如果编译JDK是21,代码仍可能误用较新标准库API。JDK 9+应优先使用--release。
Maven示例:
<properties>
<maven.compiler.release>17</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>Gradle示例:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
tasks.withType(JavaCompile).configureEach {
options.release = 21
}六、Class版本速查
| Java版本 | Class major version |
|---|---|
| Java 8 | 52 |
| Java 11 | 55 |
| Java 17 | 61 |
| Java 21 | 65 |
高版本编译产物交给低版本JVM运行,会出现:
UnsupportedClassVersionError这类错误不是“缺少依赖”,而是运行JVM无法识别更高Class版本。先检查构建机、IDE、Maven/Gradle Daemon、容器基础镜像和生产进程的JDK是否一致。
七、选哪个版本
| 场景 | 建议 |
|---|---|
| 维护历史Spring Boot 1/2项目 | 通常保留JDK 8或按框架支持升级到11/17 |
| Spring Boot 2.7存量项目 | 可运行于8及部分更高版本,具体看组件矩阵;升级JDK与升级Boot分步验证 |
| Spring Boot 3新项目 | 至少Java 17 |
| 新建高并发IO服务 | 在框架和Agent兼容时评估Java 21虚拟线程 |
| 强依赖旧Agent、JNI、内部API | 先完成兼容盘点和压测,不直接跨级上线 |
不要仅因为“21更新”就把所有项目直接升级到21;也不要因为“8稳定”永久停留在缺少新安全补丁和生态支持的旧基线。版本选择是安全、框架、依赖、运维和团队能力共同决定的工程决策。
八、升级路径
推荐将变更拆开:
flowchart TD
A["盘点当前JDK、框架、依赖、Agent"] --> B["建立功能与性能基线"]
B --> C["升级构建工具和插件"]
C --> D["先验证目标JDK运行兼容"]
D --> E["处理移除模块、反射和JVM参数"]
E --> F["再采用新语言和API"]
F --> G["灰度、观测、回滚演练"]升级检查项:
- Maven/Gradle、编译插件、测试插件和代码覆盖率插件。
- Spring、Spring Boot、ORM、数据库驱动、日志框架。
- Lombok、MapStruct等Annotation Processor。
- APM、Profiler、安全和热部署Agent。
- JNI、本地库和操作系统架构。
- JVM启动参数、GC日志和默认GC。
- TLS、证书、默认字符集和时区。
- 反射、序列化、脚本引擎和JDK内部API。
- 容器CPU/内存感知和镜像发行版。
九、面试回答模板
JDK 8、11、17、21怎么概括
JDK 8是函数式编程和现代标准库的分水岭,引入Lambda、Stream、java.time和CompletableFuture;JDK 11是模块化后的LTS,正式提供标准HTTP Client、字符串和文件便捷API、单文件源码运行,并面对Java EE/CORBA模块移除;JDK 17是现代Spring Boot 3基线,具备Record、密封类、文本块、Switch表达式和instanceof模式匹配,同时JDK内部强封装更严格;JDK 21正式引入虚拟线程、Record模式、Switch模式匹配、Sequenced Collections和分代ZGC,重点改善高并发IO代码和数据解构表达。
升级JDK为什么不能只改Docker镜像
因为运行时默认GC、JVM参数、模块封装、安全协议、移除模块、Agent和反射行为都会变化;构建插件还可能生成不同Class版本或误用新API。应先盘点依赖和参数、建立基线、升级构建链、处理兼容问题,再做灰度和回滚验证。
十、关联学习
| 专题 | 继续学习什么 |
|---|---|
| JDK 7与8版本差异 | 老项目写法、集合和并发实现变化 |
| Java 17现代基线与升级 | 8到17生产迁移Runbook |
| Lambda与Stream | JDK 8函数式编程深入 |
| CompletableFuture | 异步任务编排与线程池 |
| JVM性能调优 | GC、内存、诊断和参数 |
本章小结
四个LTS版本不是四份互不相关的特性表,而是一条连续演进线:JDK 8改变集合和异步写法,JDK 11完成模块化后的工程基线,JDK 17让不可变数据和受控类型层次成为正式语言能力,JDK 21把高并发阻塞式代码和模式匹配推向生产可用。学习时必须同时回答“何时引入、如何使用、解决什么、有什么坑、升级影响什么”。
