JDK 三十年进化史:从 1.1 到 23,三条主线一图记牢
面试官问「JDK 8 到 21 都更新了什么」,多数人的回答是从牙缝里挤名词。这篇给你一个更好的装备:不背版本清单,背三条主线——三十年 JDK 的进化,说到底就是回答三个问题的历史:
- 语言表达力——代码怎么写得更短、更不容易错(建筑风格);
- 运行时——程序怎么跑得更快、更稳(地下管网);
- 平台与生态——应用怎么打包、交付、上云(行政区划)。
把 JDK 想成一座城市:三十年里地标换了几轮(泛型、Lambda、虚拟线程),但真正决定城市面貌的,是这三套基础设施各自的演进。先上总图:
口诀先背:5 变语言,8 变写法,9 变结构,21 变线程。 LTS 锚点再背一遍:8 / 11 / 17 / 21 / 25(★ 版本,生产系统的主流驻留地)。
下面按时代走一遍,每个版本只记「一句话该记住的事」。
一、奠基时代:1.1 – 1.4(1997–2002)
Java 从「能跑 Applet 的玩具」长成平台,四块基石依次落位:
- 1.1(1997):内部类、反射、JDBC、RMI、JavaBeans——「面向对象 + 连数据库 + 组件化」的雏形全在这年。
- 1.2(1998):改名 Java 2,两大传家宝登场:Collections 集合框架(你天天用的 List/Map 就是这套)和 Swing;JIT 即时编译引入。
- 1.3(2000):HotSpot 虚拟机成为默认——此后二十年「Java 慢」的印象主要靠它翻案。
- 1.4(2002):NIO(非阻塞 IO)、正则表达式、
java.util.logging、assert关键字。网络中间件的黄金组合成型。
这个时代的记忆钩子:1.2 给了容器,1.3 给了引擎,1.4 给了高速通道。
二、语言大革命:5 – 6(2004–2006)
JDK 5(2004)是三十年里第一次「变语言」,一次塞进了现代 Java 的全部语法地基:
- 泛型——类型安全的集合(虽然是用擦除实现的,埋了后世一堆面试题);
- 注解——后来 Spring 全家桶的命根子;
- 枚举——带行为的类型安全枚举;
- 增强 for、自动装箱、可变参数、静态导入;
java.util.concurrent并发包——线程池(上一篇的主角)、ConcurrentHashMap、Lock全在这年入伍。
JDK 6(2006)相对温和:脚本引擎支持(JSR-223)、JDBC 4.0、大量桌面与启动性能优化——是那个「Java 桌面还想挣扎一下」年代的收官作。
三、过渡与 Lambda 元年:7 – 8(2011–2014)
Oracle 收购 Sun 后的第一个版本 JDK 7(2011)像一次深呼吸:try-with-resources、钻石操作符 <>、switch 支持字符串、NIO.2(Path/Files)、Fork/Join 框架、invokedynamic 字节码(为动态语言铺路,也是日后 Lambda 的地基)。
JDK 8(2014)是三十年里第二次大变,也是存量最大的一版——「变写法」:
- Lambda 表达式 + Stream API:从「怎么循环」进化到「声明要什么」,函数式风格一夜转正;
- 接口默认方法与静态方法;
Optional——向 NullPointerException 宣战;- 新日期时间 JSR-310(
LocalDate/Instant,告别SimpleDateFormat的坑); - JVM 侧:PermGen 永久代被移除,换成 Metaspace。
四、快跑时代:9 – 13(2017–2019)
从 9 开始,JDK 改成半年一发(3 月 / 9 月各一版)。发布节奏变了,心态也要变:非 LTS 版本不再是「必须升级的目标」,而是 JDK 团队的迭代脚步。
- 9(2017)第三次大变——「变结构」:模块化系统 Jigsaw 落地(
module-info.java)、JShell REPL、G1 成为默认 GC、集合工厂方法List.of()。模块化争议极大,但它换来的内部封装和启动瘦身是后来 GraalVM native-image 的地基。 - 10(2018):
var局部变量类型推断;容器感知——JVM 终于知道自己跑在 Docker 里,不再把宿主机 64 核当成自己的(这个特性救过无数 K8s 里的 Java 服务)。 - 11(2018,LTS):HTTP Client 转正(
HttpClient,异步、HTTP/2)、String 增强(isBlank/lines/strip)、单文件源码直接运行;同时移除 Java EE 模块(JAXB 一批人被赶去生态库);ZGC、Shenandoah 以实验身份登场。 - 12–13(2019):switch 表达式与文本块开始预览;ZGC 支持归还内存——「预览→转正」的两步走从这个时期成为 JDK 功能演化的标准节奏,读版本说明先看 Preview 还是 Final。
五、语法糖丰收:14 – 17(2020–2021)
- 14:switch 表达式转正;Records 预览(一行顶过去十行的数据类);instanceof 模式匹配预览;NPE 提示消息终于会告诉你哪个变量是 null(救Debug神器);CMS GC 被移除。
- 15:文本块(三引号多行字符串)转正;sealed 密封类预览;ZGC、Shenandoah 转正。
- 16:Records 转正、instanceof 模式匹配转正;Vector API 孵化;JDK 内部默认强封装(
sun.misc.Unsafe的倒计时开始)。 - 17(2021,LTS):sealed 密封类转正——「哪些类能继承我,我说了算」;模式匹配 switch 预览。作为 LTS,17 是从 8 迁移的传统第一站。
六、并发革命与云原生:18 – 23(2022–2024)
- 18(2022):UTF-8 成为默认字符集(三十年的编码坑填平);内置简易 Web 服务器
jwebserver。 - 19 – 20:虚拟线程首次预览(Project Loom 成像),结构化并发、作用域值、记录模式陆续预览——下一场革命的预告片连放两季。
- 21(2023,LTS)第四次大变——「变线程」:虚拟线程转正。百万级轻量线程,
new Thread().start()的同步写法直接吃满异步的吞吐,Tomcat/Spring Boot 3.2+ 全面跟进;同版还有:记录模式与 switch 模式匹配转正、分代 ZGC、序列化集合SequencedCollection。 - 22(2024):外部函数与内存 API(FFM)转正——取代 JNI,Java 与 C 库握手进入现代时代;G1 区域固定(虚拟线程 + synchronized 的补丁前奏);未命名变量
_。 - 23(2024.9):ZGC 默认开启分代;Markdown 写 Javadoc;模块导入声明、灵活构造器等继续预览。单看不大,但它是「预览功能流水线」里的关键中转站。
七、23 之后(截至本文写作的 2026 年)
按半年节奏,24(2025.3)和 25(2025.9,LTS)已发布,只点三件最值得记的:JDK 24 修掉了虚拟线程遇上 synchronized 会「钉住」载体线程的老毛病——虚拟线程最后一块短板补齐;类文件 API、流收集器(Gatherers)转正;AOT 类加载缓存让启动速度开始质变(Project Leyden 的第一步)。JDK 25 则把「紧凑源文件 + 实例 main」转正——Hello World 从五行变一行,作用域值、紧凑对象头转正。再往后的版本,以 openjdk.org 的 JEP 列表为准——这也是读 JDK 新闻的正确姿势:别看版本号,看 JEP 是 Preview 还是 Final。
速查表:一句话版
| 版本 | 年份 | 一句话必记 |
|---|---|---|
| 1.1 | 1997 | 内部类、反射、JDBC |
| 1.2 | 1998 | Collections 框架、Swing、JIT |
| 1.3 | 2000 | HotSpot 成为默认 JVM |
| 1.4 | 2002 | NIO、正则、日志 API |
| 5 | 2004 | 泛型、注解、枚举、并发包 |
| 6 | 2006 | 脚本引擎、JDBC 4.0 |
| 7 | 2011 | try-with-resources、NIO.2、Fork/Join |
| 8 | 2014 | Lambda、Stream、Optional、JSR-310 |
| 9 | 2017 | 模块化、JShell、G1 默认 |
| 10 | 2018 | var、容器感知 |
| 11 | 2018 | HTTP Client、ZGC 实验、移除 EE 模块 |
| 17 | 2021 | sealed 转正、模式匹配进行中 |
| 21 | 2023 | 虚拟线程、分代 ZGC、模式匹配三连转正 |
| 23 | 2024 | ZGC 默认分代、Markdown Javadoc |
| 25 | 2025 | 紧凑源文件、作用域值、紧凑对象头(LTS) |
老兵点评
- 别追版本号,追 LTS 和 JEP。半年一版是 JDK 团队的迭代节奏,不是你的升级节奏。生产的锚点始终是 LTS:8 → 11 → 17 → 21 → 25。选哪站下车,看的是你依赖的框架(Spring Boot 3.x 要求 17+,用虚拟线程就要 21+),不是新闻热度。
- Java 8 的存量庞大,不是技术问题是经济问题。升级的真正成本从来不是语法,是那批跑在老 EE 模块、老字节码增强框架上的存量资产。评估升级,先盘点依赖兼容性,再谈新特性。
- 三条主线现在是共振的。早期版本一次只动一条线;而虚拟线程(语言+运行时)、native-image(平台+运行时)说明如今的 JDK 在同时发力。这意味着「再等等看」的代价在变大——每跳过一个 LTS,你与云原生基线的距离就多一截。
带走三句话
- 口诀:5 变语言,8 变写法,9 变结构,21 变线程;LTS 锚点:8 / 11 / 17 / 21 / 25。
- 读版本新闻的正确姿势:别看版本号,看 JEP 是 Preview 还是 Final——预览是预告片,转正才进生产。
- 三条主线(语言 / 运行时 / 平台)各自演进、如今共振——升级决策看依赖与 LTS,不看热度。
本篇是「Java 工兵连」特别篇(插队)。→ 继续阅读:第 2 篇 · HashMap 的扩容与树化 | 浏览整个专栏 →。
❦ 终 ❦