这篇笔记按时间线梳理 JDK 5 到 JDK 25 的语言特性、核心类库补充以及 JVM / GC 演进,重点区分哪些变化属于语法层增强,哪些会直接影响默认运行时行为、垃圾收集策略和升级路径。
阅读时可以先看发布时间线与 LTS 版本定位,再回到对应版本章节;如果目标是做版本升级或选型,JDK 8、11、17、21、25 的差异最值得单独比较。
参考资料:
官方规范与发布说明:JDK Release Notes Index 、 Java SE 24 Specification 、 OpenJDK JEP Index
[TOC]
版本发布时间线总览
| 版本 | 发布时间 | 类型 | 核心特性 |
|---|---|---|---|
| JDK 5 | 2004-09 | - | 泛型、枚举、注解、自动装箱、并发包 |
| JDK 6 | 2006-12 | - | 脚本引擎、JDBC 4.0、JVM锁优化 |
| JDK 7 | 2011-07 | - | try-with-resources、NIO 2、Fork/Join、G1(实验) |
| JDK 8 | 2014-03 | LTS | Lambda、Stream、Optional、新日期API、元空间 |
| JDK 9 | 2017-09 | - | 模块化、JShell、集合工厂方法、G1默认GC |
| JDK 10 | 2018-03 | - | var局部变量类型推断、AppCDS |
| JDK 11 | 2018-09 | LTS | HTTP Client、ZGC(实验)、String增强、JFR开源 |
| JDK 12 | 2019-03 | - | Switch表达式(预览)、Shenandoah GC |
| JDK 13 | 2019-09 | - | 文本块(预览)、yield、动态CDS |
| JDK 14 | 2020-03 | - | instanceof模式匹配(预览)、Record(预览)、NPE增强、移除CMS |
| JDK 15 | 2020-09 | - | 文本块(正式)、封闭类(预览)、ZGC/Shenandoah正式 |
| JDK 16 | 2021-03 | - | Record(正式)、instanceof模式匹配(正式)、Stream.toList() |
| JDK 17 | 2021-09 | LTS | 封闭类(正式)、switch模式匹配(预览)、强封装内部API |
| JDK 18 | 2022-03 | - | 默认UTF-8、简易Web服务器、废弃Finalization |
| JDK 19 | 2022-09 | - | 虚拟线程(预览)、结构化并发(孵化)、Record模式(预览) |
| JDK 20 | 2023-03 | - | 作用域值(孵化)、各特性持续迭代 |
| JDK 21 | 2023-09 | LTS | 虚拟线程(正式)、Record模式(正式)、序列化集合、分代ZGC |
| JDK 22 | 2024-03 | - | FFM API(正式)、未命名变量和模式(正式)、Stream Gatherers(预览) |
| JDK 23 | 2024-09 | - | ZGC 默认启用分代模式、Markdown文档注释、模块导入声明(预览) |
| JDK 24 | 2025-03 | - | Stream Gatherers(正式)、Class-File API(正式)、虚拟线程不再pin |
| JDK 25 | 2025-09 | LTS | Scoped Values(正式)、紧凑对象头(正式)、分代Shenandoah(正式) |
LTS版本定位速览
| 版本 | 定位 | 升级时值得重点关注的变化 |
|---|---|---|
| JDK 8 | 现代 Java 的基础分界线 | Lambda / Stream、java.time、Metaspace 替代 PermGen |
| JDK 11 | 长期稳定的服务端基线 | HTTP Client、ZGC / Epsilon、JFR 开源、JDK 9~10 模块化兼容性影响开始集中体现 |
| JDK 17 | 当前主流企业基线之一 | 强封装内部 API、Security Manager 废弃、Record / Sealed Class 正式 |
| JDK 21 | 并发模型演进的重要拐点 | 虚拟线程正式、Sequenced Collections、分代 ZGC、Agent 动态加载告警 |
| JDK 25 | 新一代 LTS 基线 | Scoped Values 正式、紧凑对象头正式、分代 Shenandoah 正式、JFR / AOT 持续增强 |
flowchart LR
J8[JDK 8 LTS] --> J11[JDK 11 LTS] --> J17[JDK 17 LTS] --> J21[JDK 21 LTS] --> J25[JDK 25 LTS]
垃圾收集算法基础
对象存活判定 —— GC Roots可达性分析
JVM通过 GC Roots可达性分析 判定对象是否存活:从GC Roots出发,沿引用链遍历,不可达的对象即为可回收对象。
GC Roots 包括:
- 虚拟机栈中引用的对象(局部变量表)
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- 本地方法栈中 JNI 引用的对象
- JVM内部引用(如基本类型的Class对象、系统类加载器等)
- 所有被
synchronized持有的对象 - JMXBean、JVMTI中注册的回调等
四种基本GC算法
| 算法 | 原理 | 优点 | 缺点 | 适用区域 |
|---|---|---|---|---|
| 标记-清除 | 标记存活对象,清除未标记对象 | 简单,不需移动对象 | 内存碎片、效率不稳定 | 老年代 |
| 复制算法 | 将存活对象复制到另一半空间 | 无碎片、效率高 | 空间利用率50% | 年轻代(Eden→Survivor) |
| 标记-整理 | 标记存活对象,向一端移动并清理边界 | 无碎片 | 移动开销大 | 老年代 |
| 分代收集 | 按对象年龄分区,不同区域用不同算法 | 综合最优 | 实现复杂 | 整堆 |
分代收集理论
- 弱分代假说:绝大多数对象都是朝生夕死的
- 强分代假说:熬过越多次GC的对象越难被回收
- 跨代引用假说:跨代引用相对同代引用占极少数(使用记忆集/卡表优化)
七种主流垃圾收集器详解
1. Serial GC(串行收集器)
- 引入版本:JDK 1.3
- 作用区域:年轻代(Serial)+ 老年代(Serial Old)
- 算法:年轻代复制算法,老年代标记-整理
- 线程模型:单线程,STW(Stop The World)
- 特点:简单高效,无线程交互开销,适合单核/小堆/客户端
- 参数:
-XX:+UseSerialGC
2. Parallel GC(并行收集器/吞吐量收集器)
- 引入版本:JDK 1.4(Parallel Scavenge),JDK 5默认(Server模式)
- 作用区域:年轻代(Parallel Scavenge)+ 老年代(Parallel Old)
- 算法:年轻代复制算法,老年代标记-整理
- 线程模型:多线程并行收集,STW
- 特点:以吞吐量为目标,支持自适应调节策略
- 关键参数:
-XX:+UseParallelGC:启用-XX:ParallelGCThreads=N:GC线程数-XX:MaxGCPauseMillis=ms:最大停顿时间目标-XX:GCTimeRatio=N:吞吐量目标(1/(1+N)的时间用于GC)-XX:+UseAdaptiveSizePolicy:自适应策略
3. CMS(Concurrent Mark Sweep)
- 引入版本:JDK 1.4,JDK 9废弃,JDK 14移除
- 作用区域:老年代
- 算法:标记-清除(不压缩)
- 线程模型:并发收集,大部分阶段与用户线程并发执行
- 工作阶段:
- 初始标记(STW):标记GC Roots直接关联的对象,极快
- 并发标记:从GC Roots遍历整个对象图,与用户线程并发
- 重新标记(STW):修正并发标记期间变化的引用,使用增量更新
- 并发清除:清除不可达对象,与用户线程并发
- 缺点:内存碎片、浮动垃圾、CPU敏感、并发失败退化Serial Old
- 参数:
-XX:+UseConcMarkSweepGC(JDK14+报错)
4. G1(Garbage-First)
- 引入版本:JDK 7实验性,JDK 9正式成为默认GC
- 作用区域:整堆(Region化,不再物理分代)
- 算法:整体标记-整理,局部复制算法
- 线程模型:并发+并行
- 核心设计:
- 堆划分为2048个等大Region(1MB~32MB)
- 逻辑分代:Eden/Survivor/Old/Humongous Region
- 优先回收垃圾最多的Region(Garbage-First)
- 可预测的停顿时间模型:
-XX:MaxGCPauseMillis=200(默认200ms)
- 工作阶段:
- 初始标记(STW):标记GC Roots,借用Minor GC
- 并发标记:对象图遍历,使用SATB(原始快照)算法
- 最终标记(STW):处理SATB缓冲区
- 筛选回收(STW):按回收价值排序Region,复制存活对象
- 关键参数:
-XX:+UseG1GC-XX:G1HeapRegionSize=n:Region大小-XX:MaxGCPauseMillis=200:目标停顿时间-XX:G1NewSizePercent=5:年轻代最小比例-XX:G1MaxNewSizePercent=60:年轻代最大比例-XX:InitiatingHeapOccupancyPercent=45:触发并发标记的堆占用率
5. ZGC
- 引入版本:JDK 11实验性,JDK 15正式发布,JDK 21引入分代
- 作用区域:整堆
- 算法:标记-整理(并发重定位)
- 线程模型:几乎全并发,停顿目标为低毫秒级
- 核心技术:
- 着色指针(Colored Pointers):利用64位指针中的4位存储GC元数据(Marked0/Marked1/Remapped/Finalizable)
- 读屏障(Load Barrier):在对象引用加载时检查指针状态,触发自愈
- 多重映射(Multi-Mapping):同一物理内存映射到多个虚拟地址
- 工作阶段:
- 并发标记:遍历对象图,标记存活对象
- 并发预备重分配:选择需要清理的Region
- 并发重分配:移动存活对象到新Region,建立转发表
- 并发重映射:修复指向旧地址的引用(可延迟到下次GC标记阶段)
- 关键参数:
-XX:+UseZGC-XX:+ZGenerational(JDK21 分代ZGC)-XX:ZAllocationSpikeTolerance=2-XX:ZCollectionInterval=0(0=只在必要时GC)-XX:SoftMaxHeapSize=4g(软上限)
6. Shenandoah GC
- 引入版本:JDK 12实验性,JDK 15正式发布
- 作用区域:整堆
- 算法:标记-整理(并发压缩)
- 线程模型:几乎全并发
- 核心技术:
- Brooks转发指针:每个对象头前增加一个间接指针,指向对象当前实际位置
- 写屏障(Write Barrier):在引用更新时维护转发指针一致性
- 连接矩阵(Connection Matrix):替代G1的记忆集,记录Region间引用关系
- 工作阶段:
- 初始标记(STW):标记GC Roots
- 并发标记:遍历对象图
- 最终标记(STW):处理剩余SATB、选择回收集
- 并发清理:回收无存活对象的Region
- 并发疏散:将回收集中存活对象复制到其他Region(与用户线程并发!)
- 初始引用更新(STW):确保所有GC线程完成疏散
- 并发引用更新:修复堆中所有旧引用
- 最终引用更新(STW):修复GC Roots引用
- 参数:
-XX:+UseShenandoahGC
7. Epsilon GC
- 引入版本:JDK 11
- 作用区域:不进行任何回收
- 算法:无(No-Op)
- 特点:只分配不回收,堆满即OOM
- 用途:性能基准测试、极短生命周期程序、内存压力测试
- 参数:
-XX:+UseEpsilonGC
ZGC vs Shenandoah 对比
| 维度 | ZGC | Shenandoah |
|---|---|---|
| 开发者 | Oracle | Red Hat |
| 核心技术 | 着色指针 + 读屏障 | Brooks转发指针 + 写屏障 |
| 指针开销 | 无额外空间(复用指针位) | 每对象+1指针字(8字节) |
| 屏障类型 | 读屏障(Load Barrier) | 写屏障(Write Barrier) |
| 并发压缩 | 并发重定位 + 转发表 | 并发疏散 + Brooks指针 |
| 分代支持 | JDK 21引入分代ZGC | 不分代 |
| 堆大小 | 8MB ~ 16TB | 无明确上限 |
| 停顿时间 | 低毫秒级,主要与 GC Roots / 线程栈扫描相关 | 低毫秒级到十毫秒级,通常不随堆大小线性增长 |
| 内存占用 | 较高(多重映射) | 较高(转发指针) |
| 平台支持 | Linux/macOS/Windows | Linux/macOS/Windows |
| JDK发行版 | Oracle JDK / OpenJDK | OpenJDK(非Oracle JDK) |
GC组合关系(JDK 8时代)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
年轻代收集器 老年代收集器
┌────────────┐ ┌────────────────┐
│ Serial │─────→│ Serial Old │
├────────────┤ ├────────────────┤
│ ParNew │─────→│ CMS │
├────────────┤ │ (并发标记清除) │
│ Parallel │─────→├────────────────┤
│ Scavenge │─────→│ Parallel Old │
└────────────┘ └────────────────┘
可搭配组合:
Serial + Serial Old (客户端默认)
Serial + CMS
ParNew + Serial Old
ParNew + CMS (JDK8常用低延迟方案)
Parallel + Serial Old (已废弃)
Parallel + Parallel Old (JDK8 Server默认,吞吐量优先)
注:JDK 9+ G1/ZGC/Shenandoah 为整堆收集器,不存在搭配问题
GC选择决策树
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
你的应用需要什么?
│
├─ 吞吐量最大化(批处理/科学计算)
│ └─→ Parallel GC
│
├─ 延迟敏感(Web服务/API)
│ ├─ 堆 < 4GB
│ │ └─→ G1 GC
│ ├─ 堆 4GB ~ 32GB
│ │ └─→ G1 GC 或 Shenandoah
│ └─ 堆 > 32GB 或 要求 <1ms 停顿
│ └─→ ZGC
│
├─ 资源受限(嵌入式/容器小内存)
│ └─→ Serial GC
│
└─ 性能测试/短命程序
└─→ Epsilon GC
GC选择指南总结
| GC | 适用场景 | 特点 | 启用参数 |
|---|---|---|---|
| Serial GC | 单核/小内存/客户端 | 单线程收集,简单高效 | -XX:+UseSerialGC |
| Parallel GC | 吞吐量优先/批处理 | 多线程收集,JDK8默认 | -XX:+UseParallelGC |
| G1 GC | 大堆/平衡延迟与吞吐 | Region化,可预测停顿,JDK9+默认 | -XX:+UseG1GC |
| ZGC | 超低延迟/大堆(TB级) | 低毫秒级停顿,并发收集,JDK23起启用 ZGC 时默认使用分代模式 | -XX:+UseZGC |
| Shenandoah | 低延迟/中大堆 | 并发压缩,转发指针 | -XX:+UseShenandoahGC |
| Epsilon | 性能测试/无GC需求 | 不回收内存 | -XX:+UseEpsilonGC |
GC全维度对比表
| 维度 | Serial | Parallel | CMS | G1 | ZGC | Shenandoah | Epsilon |
|---|---|---|---|---|---|---|---|
| 引入版本 | JDK1.3 | JDK1.4 | JDK1.4 | JDK7 | JDK11 | JDK12 | JDK11 |
| 正式版本 | - | - | - | JDK9 | JDK15 | JDK15 | JDK11 |
| 默认版本 | - | JDK5~8 | - | JDK9至今(默认GC) | 非默认GC;JDK23起启用时默认使用分代模式 | 非默认GC | - |
| 线程模型 | 单线程 | 多线程并行 | 并发+并行 | 并发+并行 | 几乎全并发 | 几乎全并发 | 无GC线程 |
| 算法 | 复制+标记整理 | 复制+标记整理 | 标记清除 | 复制+标记整理 | 标记整理 | 标记整理 | 无 |
| 分代 | 是 | 是 | 是(仅老年代) | 是(逻辑分代) | JDK21起(JDK23默认) | 否 | 无 |
| 压缩 | 是 | 是 | 否 | 是 | 是 | 是 | 无 |
| 最大停顿 | 高(秒级) | 中(百ms) | 低(几十ms) | 可控(百ms内) | 低毫秒级 | 低毫秒级到十毫秒级 | 无停顿 |
| 吞吐量 | 低 | 高 | 中 | 中高 | 中 | 中 | 最高(无GC开销) |
| 堆大小建议 | <几百MB | 几百MB~几GB | <32GB | 几GB~几十GB | 8MB~16TB | 无限制 | 任意 |
| 内存碎片 | 无 | 无 | 有 | 无 | 无 | 无 | 无(不回收) |
| 核心技术 | - | 自适应策略 | 增量更新 | SATB+Region | 着色指针+读屏障 | Brooks指针+写屏障 | - |
| 状态 | 可用 | 可用 | JDK14移除 | 推荐 | 推荐 | 可用 | 可用 |
JVM内存模型演进一览
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
JDK 7以前:
┌─────────────────────────────────────────┐
│ JVM Heap │
│ ┌──────────┐ ┌──────────┐ ┌────────┐│
│ │ Young Gen │ │ Old Gen │ │PermGen ││
│ │(Eden+S0+S1)│ │ │ │(固定大小)││
│ └──────────┘ └──────────┘ └────────┘│
└─────────────────────────────────────────┘
JDK 8+:
┌──────────────────────────────┐ ┌─────────────┐
│ JVM Heap │ │ Native Memory│
│ ┌──────────┐ ┌──────────┐ │ │ ┌─────────┐ │
│ │ Young Gen │ │ Old Gen │ │ │ │Metaspace│ │
│ │(Eden+S0+S1)│ │ │ │ │ │(动态扩展) │ │
│ └──────────┘ └──────────┘ │ │ └─────────┘ │
└──────────────────────────────┘ └─────────────┘
JDK 9+ G1默认(Region化):
┌─────────────────────────────────────────┐
│ ┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐ │
│ │E ││E ││S ││O ││O ││H ││O ││E ││S │ │
│ └──┘└──┘└──┘└──┘└──┘└──┘└──┘└──┘└──┘ │
│ E=Eden S=Survivor O=Old H=Humongous │
└─────────────────────────────────────────┘
JDK 21+ 分代ZGC:
┌─────────────────────────────────────────┐
│ ZPages (dynamically sized: 2MB/32MB/N*2MB)│
│ ┌──────────────────┐ ┌──────────────┐│
│ │ Young Generation │ │ Old Generation││
│ │ (高频收集、着色指针) │ │ (低频收集) ││
│ └──────────────────┘ └──────────────┘│
│ 特点:停顿<1ms、支持8MB~16TB、读屏障+多重映射 │
└─────────────────────────────────────────┘
JDK 5(2004年9月)
JDK 5 是Java发展史上里程碑式的版本,引入了大量语言层面的改进。
1. 泛型(Generics)
提供编译时类型安全检查,消除强制类型转换。
1
2
3
4
5
6
7
8
9
// JDK5之前
List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);
// JDK5之后
List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0); // 无需强制转换
2. 增强for循环(For-each)
简化集合和数组的遍历操作。
1
2
3
4
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.println(num);
}
3. 自动装箱与拆箱(Autoboxing/Unboxing)
基本类型与其包装类之间的自动转换。
1
2
Integer i = 10; // 自动装箱 int -> Integer
int n = i; // 自动拆箱 Integer -> int
4. 枚举类型(Enum)
类型安全的枚举,替代之前的常量接口模式。
1
2
3
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER;
}
5. 可变参数(Varargs)
允许方法接收可变数量的参数。
1
2
3
4
5
public void print(String... args) {
for (String s : args) {
System.out.println(s);
}
}
6. 注解(Annotations)
引入元数据机制,支持 @Override、@Deprecated、@SuppressWarnings 等内置注解,并支持自定义注解。
1
2
3
4
5
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value();
}
7. 静态导入(Static Import)
可以直接使用静态方法和字段,无需通过类名限定。
1
2
3
import static java.lang.Math.*;
double r = sqrt(pow(3, 2) + pow(4, 2));
8. 并发工具包(java.util.concurrent)
JDK 5 引入了完整的并发编程框架:
- 线程池:
Executor、ExecutorService、ThreadPoolExecutor、ScheduledExecutorService - 并发集合:
ConcurrentHashMap(分段锁实现)、CopyOnWriteArrayList、ConcurrentLinkedQueue - 同步工具:
CountDownLatch、CyclicBarrier、Semaphore、Exchanger - 锁机制:
ReentrantLock、ReadWriteLock、Condition - 原子类:
AtomicInteger、AtomicLong、AtomicReference(基于CAS) - 阻塞队列:
ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue - Future模式:
Callable、Future、FutureTask
9. 其他
- 协变返回类型(Covariant Return Types)
StringBuilder类(非线程安全的替代StringBuffer)java.util.ScannerProcessBuilderjava.lang.instrument:支持Java Agent字节码增强
JDK 6(2006年12月)
JDK 6 主要是性能和工具链方面的改进,语言层面变化较小。
1. 脚本引擎支持(Scripting API - JSR 223)
内置 JavaScript 引擎(Rhino),支持在Java中执行脚本语言。
1
2
3
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
engine.eval("print('Hello from JavaScript')");
2. JDBC 4.0
自动加载数据库驱动,无需显式调用 Class.forName()。
3. Java Compiler API(JSR 199)
提供编程方式访问Java编译器的API。
4. 可插拔注解处理(JSR 269)
支持编译时注解处理器,为后来的 Lombok 等工具提供了基础。
5. JVM改进
- 同步优化(偏向锁、锁消除、锁粗化、自适应自旋锁)
- 逃逸分析(Escape Analysis):支持栈上分配和标量替换
- 分层编译初步引入:结合C1快速编译和C2深度优化
- 垃圾回收器改进:Parallel GC吞吐量提升,CMS稳定性增强
- 类加载优化
6. 其他
@Override支持接口方法Desktop和SystemTray类(桌面集成)JAXB 2.0、JAX-WS 2.0集成- 轻量级 HTTP Server API
Console类
JDK 7(2011年7月)
1. switch支持String
1
2
3
4
5
6
7
8
9
String day = "Monday";
switch (day) {
case "Monday":
System.out.println("周一");
break;
case "Tuesday":
System.out.println("周二");
break;
}
2. try-with-resources
自动关闭实现了 AutoCloseable 接口的资源。
1
2
3
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line = br.readLine();
}
3. 钻石操作符(Diamond Operator)
类型推断简化泛型实例化。
1
List<String> list = new ArrayList<>(); // 无需重复指定泛型类型
4. 多异常捕获(Multi-catch)
单个 catch 块可以捕获多种异常类型。
1
2
3
4
5
try {
// ...
} catch (IOException | SQLException e) {
e.printStackTrace();
}
5. 数值字面量增强
- 二进制字面量:
int binary = 0b1010; - 数字下划线分隔:
int million = 1_000_000;
6. NIO 2.0(java.nio.file)
引入 Path、Files、FileSystem 等新API,支持文件系统操作、文件变更监听(WatchService)。
1
2
Path path = Paths.get("/tmp/test.txt");
List<String> lines = Files.readAllLines(path);
7. Fork/Join框架
支持并行任务分解执行的框架。
1
2
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(new RecursiveTask());
8. 其他
invokedynamic字节码指令(为JDK8 Lambda做铺垫)- G1垃圾收集器(实验性):Region化内存布局,可预测停顿时间
- 压缩对象指针(Compressed Oops)默认开启
- 分层编译默认开启
Objects工具类- HashMap并发问题:JDK7的头插法在并发扩容时可能导致链表成环(死循环)
ConcurrentLinkedDeque无锁并发双端队列
JDK 8(2014年3月)⭐ LTS
JDK 8 是现代Java的分水岭,引入了函数式编程范式。
1. Lambda表达式
简化匿名内部类的写法,支持函数式编程。
1
2
3
4
List<String> list = Arrays.asList("a", "b", "c");
list.forEach(item -> System.out.println(item));
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));
2. 函数式接口(Functional Interface)
只有一个抽象方法的接口,配合 Lambda 使用。核心接口:
| 接口 | 方法 | 说明 |
|---|---|---|
Consumer<T> |
void accept(T t) |
消费型:有参数无返回值 |
Supplier<T> |
T get() |
供给型:无参数有返回值 |
Function<T,R> |
R apply(T t) |
函数型:有参数有返回值 |
Predicate<T> |
boolean test(T t) |
断言型:判断真假 |
3. 方法引用(Method Reference)
Lambda 表达式的简写形式。
1
2
3
list.forEach(System.out::println); // 对象方法引用
Arrays.sort(arr, Integer::compareTo); // 实例方法引用
Supplier<List> s = ArrayList::new; // 构造器引用
4. Stream API
集合的函数式操作流,支持链式调用和并行处理。
1
2
3
4
5
List<String> result = list.stream()
.filter(s -> s.startsWith("a"))
.map(String::toUpperCase)
.sorted()
.collect(Collectors.toList());
5. Optional类
解决空指针问题的容器类。
1
2
3
Optional<String> opt = Optional.ofNullable(getName());
String name = opt.orElse("default");
opt.ifPresent(System.out::println);
6. 新的日期时间API(java.time)
替代旧的 Date/Calendar,线程安全且不可变。
1
2
3
LocalDate date = LocalDate.now();
LocalDateTime dateTime = LocalDateTime.of(2024, 1, 1, 12, 0);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
7. 接口默认方法和静态方法
1
2
3
4
5
6
7
8
public interface MyInterface {
default void defaultMethod() {
System.out.println("默认方法实现");
}
static void staticMethod() {
System.out.println("静态方法");
}
}
8. 集合框架重大改进
HashMap 引入红黑树
JDK 8 对 HashMap 的底层实现做了重大优化:
- 数据结构:数组 + 链表 + 红黑树(JDK7只有数组+链表)
- 树化阈值:当链表长度 ≥ 8 且数组长度 ≥ 64 时,链表转为红黑树
- 退化阈值:红黑树节点数 ≤ 6 时退化为链表
- 哈希冲突性能:最坏情况从 O(n) 优化到 O(log n)
- 插入方式:从头插法改为尾插法(解决并发扩容时的死循环问题)
- 扩容优化:采用高低位拆分,无需重新计算hash
1
2
3
4
5
// JDK8 HashMap关键常量
static final int TREEIFY_THRESHOLD = 8; // 链表转红黑树阈值
static final int UNTREEIFY_THRESHOLD = 6; // 红黑树退化链表阈值
static final int MIN_TREEIFY_CAPACITY = 64;// 树化最小表容量
static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认负载因子
ConcurrentHashMap 全面重写
- JDK7:分段锁(Segment + ReentrantLock),默认16个Segment,并发度固定
- JDK8:抛弃Segment,采用 CAS + synchronized + 红黑树
- 锁粒度细化到每个桶(Node)
- 空桶插入使用CAS操作
- 非空桶插入使用synchronized锁住头节点
- 同样支持链表转红黑树(阈值8)
size()用baseCount+CounterCell[]实现无锁计数(类似LongAdder)- 并发性能大幅提升
1
2
3
4
5
6
7
// JDK8 ConcurrentHashMap 插入简化逻辑
if (tab[i] == null)
casTabAt(tab, i, null, new Node(hash, key, value)); // CAS插入
else
synchronized (f) { // 锁头节点
// 链表或红黑树插入操作
}
其他集合改进
LinkedHashMap新增removeEldestEntry()配合实现LRU缓存- 所有集合类新增
forEach()、removeIf()、replaceAll()、sort()等默认方法 Map新增getOrDefault()、putIfAbsent()、compute()、merge()等方法Spliterator:并行遍历器,为 Stream 并行操作提供基础
9. 永久代移除,使用元空间(Metaspace)
元空间使用本地内存,不再受限于JVM堆大小,解决了 PermGen OutOfMemoryError 问题。
- 类元数据从JVM堆迁移到本地内存
-XX:MetaspaceSize:设置初始阈值(超过触发Full GC)-XX:MaxMetaspaceSize:设置最大值(默认无限制)- Lambda通过
invokedynamic+LambdaMetafactory实现,避免生成大量匿名内部类
10. 并发编程增强
CompletableFuture:异步编程框架,支持链式调用、组合多个异步任务StampedLock:乐观读锁,比ReadWriteLock性能更高LongAdder/DoubleAdder:高并发计数器,比AtomicLong性能更好(分段累加)LongAccumulator:通用累加器
1
2
3
4
5
6
// CompletableFuture 组合异步操作
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> queryDB())
.thenApplyAsync(result -> process(result))
.thenCombine(anotherFuture, (r1, r2) -> merge(r1, r2))
.exceptionally(ex -> handleError(ex));
11. 其他
- 重复注解
@Repeatable - 类型注解
NashornJavaScript引擎(替代Rhino)- Base64 编码API
- 并行数组操作
Arrays.parallelSort() StringJoiner字符串拼接工具
JDK 9(2017年9月)
1. 模块化系统(Project Jigsaw - JPMS)
将JDK拆分为多个模块,实现更强的封装性和更小的运行时镜像。
1
2
3
4
5
6
// module-info.java
module com.example.app {
requires java.base;
requires java.sql;
exports com.example.api;
}
2. JShell(交互式编程工具)
Java的REPL工具,支持即时执行Java代码片段。
1
2
3
jshell> int x = 10;
jshell> System.out.println(x * 2);
20
3. 接口私有方法
接口中可以定义私有方法,用于默认方法的代码复用。
1
2
3
4
5
6
7
8
public interface MyInterface {
private void helper() {
// 私有辅助方法
}
default void doSomething() {
helper();
}
}
4. 集合工厂方法
使用 of() 方法快速创建不可变集合。
1
2
3
4
5
6
7
8
List<String> list = List.of("a", "b", "c");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("key1", 1, "key2", 2);
// 超过10个KV对用 Map.ofEntries()
Map<String, Integer> bigMap = Map.ofEntries(
Map.entry("a", 1),
Map.entry("b", 2)
);
重要特性:
- 返回的集合是真正不可变的(add/remove/set 抛
UnsupportedOperationException) - 不允许null元素(与
Collections.unmodifiableList()不同) - Set/Map不允许重复元素/key
5. 改进的Stream API
新增方法:takeWhile()、dropWhile()、ofNullable()、iterate() 重载。
1
2
3
Stream.of(1, 2, 3, 4, 5)
.takeWhile(n -> n < 4) // [1, 2, 3]
.forEach(System.out::println);
6. 改进的try-with-resources
允许在 try 中使用 able-final 变量。
1
2
3
4
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try (br) { // 无需重新声明
String line = br.readLine();
}
7. 改进的Optional
新增 ifPresentOrElse()、or()、stream() 方法。
8. 改进的Process API
1
2
ProcessHandle current = ProcessHandle.current();
System.out.println("PID: " + current.pid());
9. 响应式流(Reactive Streams)
引入 Flow API,支持发布-订阅模式。
10. 其他
- HTTP/2 Client(孵化中)
- 多版本JAR文件
- 钻石操作符支持匿名内部类
@SafeVarargs可用于私有方法- G1成为默认GC:替代Parallel GC,面向低延迟场景
- 统一JVM日志:
-Xlog:gc*替代旧的-XX:+PrintGCDetails - Compact Strings:String内部从
char[]改为byte[],纯Latin-1字符串内存减半 - Indify String Concatenation:字符串拼接使用
invokedynamic优化 CompletableFuture增强
JDK 10(2018年3月)
1. 局部变量类型推断(var)
使用 var 关键字代替显式类型声明(仅限局部变量)。
1
2
3
4
5
var list = new ArrayList<String>();
var stream = list.stream();
var map = Map.of("key", "value");
// 不能用于:成员变量、方法参数、返回值类型
2. 不可变集合增强
List.copyOf()、Set.copyOf()、Map.copyOf();Collectors.toUnmodifiableList() 等。
1
2
List<String> copy = List.copyOf(originalList);
var unmodifiable = list.stream().collect(Collectors.toUnmodifiableList());
3. G1垃圾收集器并行Full GC
改善G1在Full GC时的停顿时间。
4. 应用程序类数据共享(AppCDS)
扩展类数据共享(CDS)功能到应用类,加速启动时间。
5. 线程局部管控
允许在不执行全局VM安全点的情况下对线程执行回调。
6. 其他
- 基于Java的实验性JIT编译器(Graal)
- 根证书(CA)
- 堆分配在备用内存设备上
Optional.orElseThrow()无参方法
JDK 11(2018年9月)⭐ LTS
1. HTTP Client API(正式版)
支持 HTTP/1.1 和 HTTP/2,同步和异步请求。
1
2
3
4
5
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
2. String新增方法
1
2
3
4
5
6
" hello ".strip(); // "hello" (支持Unicode空白)
" hello ".stripLeading(); // "hello "
" hello ".stripTrailing();// " hello"
"".isBlank(); // true
"line1\nline2".lines(); // Stream<String>
"ha".repeat(3); // "hahaha"
3. 文件读写增强
1
2
3
Path path = Path.of("test.txt");
String content = Files.readString(path);
Files.writeString(path, "Hello JDK 11");
4. Lambda参数的局部变量语法
Lambda表达式参数可以使用 var,主要是为了支持注解。
1
(@NonNull var x, @Nullable var y) -> x + y
5. 新的垃圾收集器
- ZGC(实验性):
- 可伸缩低延迟GC,停顿时间不超过10ms且不随堆大小增长
- 支持8MB~16TB堆内存
- 使用着色指针(Colored Pointers)和读屏障(Load Barriers)
- 所有昂贵操作均与应用线程并发执行
- Epsilon GC:不执行任何垃圾回收的GC(用于性能测试、极短生命周期应用)
- JFR开源:飞行记录器低开销(<2%)性能采集框架,记录GC事件、线程活动等
6. 直接运行Java文件
1
java HelloWorld.java # 无需先javac编译
7. 其他
- Flight Recorder(开源)
- 嵌套类访问控制(Nest-Based Access Control)
- 动态类文件常量(
CONSTANT_Dynamic) - 移除 Java EE 和 CORBA 模块
- 废弃 Nashorn JavaScript 引擎
JDK 12(2019年3月)
1. Switch表达式(预览)
支持箭头语法和返回值。
1
2
3
4
5
6
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
};
2. Shenandoah GC(实验性)
由Red Hat开发的低暂停时间垃圾收集器,与应用线程并发执行压缩。
- 停顿时间与堆大小无关
- 使用Brooks转发指针 + 写屏障实现并发移动
- 与ZGC的区别:Shenandoah用转发指针+写屏障,ZGC用着色指针+读屏障
3. JVM常量API
java.lang.constant 包,描述class文件和运行时的关键类信息。
4. 微基准测试套件
集成JMH(Java Microbenchmark Harness)。
5. 其他
- G1收集器优化:可中止的混合收集、及时归还未使用的内存
- 默认CDS归档
- String新增
indent()、transform()方法 Files.mismatch()方法Collectors.teeing()方法CompactNumberFormat
JDK 13(2019年9月)
1. 文本块(预览)
多行字符串字面量,使用三引号 """ 定义。
1
2
3
4
5
6
String json = """
{
"name": "Java",
"version": 13
}
""";
2. Switch表达式增强(第二次预览)
引入 yield 关键字用于在代码块中返回值。
1
2
3
4
5
6
7
8
int result = switch (mode) {
case "a" -> 1;
case "b" -> 2;
default -> {
int temp = compute();
yield temp;
}
};
3. ZGC改进
归还未使用的内存给操作系统。
4. 重新实现旧版Socket API
使用更现代的实现替换 java.net.Socket 和 java.net.ServerSocket 的底层实现。
5. 动态CDS归档
在应用退出时自动生成CDS归档文件。
JDK 14(2020年3月)
1. instanceof模式匹配(预览)
消除显式类型转换。
1
2
3
4
5
6
7
8
9
10
// JDK14之前
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}
// JDK14之后
if (obj instanceof String s) {
System.out.println(s.length());
}
2. Record类(预览)
简化不可变数据载体类的创建。
1
2
3
4
5
public record Point(int x, int y) {}
// 自动生成:构造器、getter、equals()、hashCode()、toString()
Point p = new Point(1, 2);
System.out.println(p.x()); // 1
3. Switch表达式(正式)
JDK 12/13 预览的switch表达式正式发布。
4. 更有帮助的NullPointerException
精确指出哪个变量为null。
1
2
// 之前:NullPointerException
// 之后:Cannot invoke "String.length()" because "a.b.name" is null
5. 文本块(第二次预览)
新增转义序列:\(行尾续行)、\s(显式空格)。
6. 其他
- 移除CMS垃圾收集器:JDK9废弃、JDK14正式移除,推荐迁移到G1或ZGC
- 废弃 ParallelScavenge + SerialOld GC 组合
- ZGC支持macOS和Windows(之前仅Linux)
- 外部内存访问API(孵化):安全高效地访问堆外内存,替代Unsafe
- JFR事件流:支持实时消费JFR事件,无需落盘
jpackage打包工具(孵化)
JDK 15(2020年9月)
1. 文本块(正式)
经过两轮预览后正式发布。
2. 封闭类(Sealed Classes,预览)
限制哪些类可以继承或实现。
1
2
3
4
5
public sealed class Shape permits Circle, Rectangle, Triangle {}
public final class Circle extends Shape {}
public non-sealed class Rectangle extends Shape {}
public sealed class Triangle extends Shape permits RightTriangle {}
3. 隐藏类(Hidden Classes)
供框架使用的不可发现的类,用于替代 Unsafe.defineAnonymousClass()。
4. ZGC(正式)
从实验性功能变为正式生产可用。
5. Shenandoah GC(正式)
从实验性功能变为正式生产可用。
6. Edwards-Curve数字签名算法
新增 EdDSA 签名算法。
7. 其他
- Record类(第二次预览)
- instanceof模式匹配(第二次预览)
- 外部内存访问API(第二次孵化)
- 废弃并禁用偏向锁
- 移除Nashorn JavaScript引擎
- 重新实现DatagramSocket API
JDK 16(2021年3月)
1. Record类(正式)
经过两轮预览后正式发布。
1
2
3
4
5
6
public record User(String name, int age) {
// 可以自定义紧凑构造器
public User {
if (age < 0) throw new IllegalArgumentException();
}
}
2. instanceof模式匹配(正式)
正式发布。
3. 封闭类(第二次预览)
4. Stream.toList()
直接收集为不可变List,无需 Collectors.toList()。
1
List<String> result = stream.toList();
5. Vector API(孵化)
SIMD向量计算API,充分利用CPU向量指令。
6. 外部链接器API(孵化)
替代JNI,提供纯Java方式访问本地代码。
7. 其他
- jpackage打包工具(正式)
- Unix域套接字
- 弹性元空间
- ZGC并发线程栈处理
- 默认强封装JDK内部API
- Alpine Linux / musl支持
JDK 17(2021年9月)⭐ LTS
1. 封闭类(Sealed Classes,正式)
正式发布,配合模式匹配实现类型安全的多态。
1
2
3
public sealed interface Shape permits Circle, Rectangle {}
public record Circle(double radius) implements Shape {}
public record Rectangle(double w, double h) implements Shape {}
2. switch模式匹配(预览)
switch支持类型模式匹配。
1
2
3
4
5
6
7
8
static String describe(Object obj) {
return switch (obj) {
case Integer i -> "整数: " + i;
case String s -> "字符串: " + s;
case null -> "空值";
default -> "其他: " + obj;
};
}
3. 增强版伪随机数生成器
新增 RandomGenerator 接口,提供多种算法实现。
1
2
RandomGenerator generator = RandomGeneratorFactory.of("L64X128MixRandom").create();
int random = generator.nextInt(100);
4. 移除实验性AOT和JIT编译器
移除了基于Graal的实验性提前编译和JIT编译器。
5. 废弃Applet API
标记为废弃,准备后续移除。
6. 外部函数和内存API(孵化)
合并了外部内存访问API和外部链接器API。
7. 其他
- 恢复始终严格的浮点语义
- 增强的伪随机数生成器
- macOS/AArch64 端口
- 废弃Security Manager
- 强封装JDK内部API(默认不允许
--illegal-access) - 上下文特定的反序列化过滤器
- Vector API(第二次孵化)
JDK 18(2022年3月)
1. 默认UTF-8字符集
Charset.defaultCharset() 在所有平台默认返回UTF-8。
2. 简易Web服务器
命令行工具快速启动静态文件服务器。
1
jwebserver -p 8080 -d /path/to/dir
3. 代码片段API(JavaDoc)
@snippet 标签,支持在JavaDoc中嵌入可验证的代码片段。
1
2
3
4
5
6
/**
* {@snippet :
* var list = List.of("a", "b", "c");
* list.forEach(System.out::println);
* }
*/
4. 使用方法句柄重新实现反射核心
使用 MethodHandle 重写 java.lang.reflect 的核心代码。
5. 其他
- Vector API(第三次孵化)
- 互联网地址解析SPI
- 外部函数和内存API(第二次孵化)
- switch模式匹配(第二次预览)
- 废弃Finalization
JDK 19(2022年9月)
1. 虚拟线程(预览 - Project Loom)
轻量级线程,极大提升并发能力。
1
2
3
4
5
6
7
8
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
2. 结构化并发(孵化)
将相关的并发任务作为一个单元来管理。
1
2
3
4
5
6
7
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> findUser());
Future<Integer> order = scope.fork(() -> fetchOrder());
scope.join();
scope.throwIfFailed();
return new Response(user.resultNow(), order.resultNow());
}
3. Record模式(预览)
解构Record类的模式匹配。
1
2
3
4
5
record Point(int x, int y) {}
if (obj instanceof Point(int x, int y)) {
System.out.println(x + y);
}
4. 其他
- switch模式匹配(第三次预览)
- 外部函数和内存API(预览)
- Vector API(第四次孵化)
JDK 20(2023年3月)
1. 作用域值(Scoped Values,孵化)
替代 ThreadLocal 的更安全、高效的线程间数据共享方式。
1
2
3
4
5
final static ScopedValue<String> USER = ScopedValue.newInstance();
ScopedValue.where(USER, "admin").run(() -> {
System.out.println(USER.get()); // "admin"
});
2. Record模式(第二次预览)
3. switch模式匹配(第四次预览)
4. 虚拟线程(第二次预览)
5. 结构化并发(第二次孵化)
6. 外部函数和内存API(第二次预览)
7. Vector API(第五次孵化)
JDK 21(2023年9月)⭐ LTS
JDK 21 是继8、11、17后的又一个长期支持版本,多个重要特性正式发布。
1. 虚拟线程(正式)
轻量级线程正式发布,每个虚拟线程仅占用几KB内存,可以轻松创建百万级线程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 创建虚拟线程
Thread.startVirtualThread(() -> {
System.out.println("Hello from virtual thread!");
});
// 使用虚拟线程执行器
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 100_000; i++) {
executor.submit(() -> {
// 每个任务在独立的虚拟线程中执行
Thread.sleep(Duration.ofMillis(100));
return "done";
});
}
}
2. Record模式(正式)
解构Record类实例,支持嵌套模式。
1
2
3
4
5
6
7
record Point(int x, int y) {}
record Line(Point start, Point end) {}
// 嵌套解构
if (obj instanceof Line(Point(var x1, var y1), Point(var x2, var y2))) {
double length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}
3. switch模式匹配(正式)
完整的模式匹配switch表达式正式发布。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static double getArea(Shape shape) {
return switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case null -> 0;
};
}
// 带守卫条件
static String classify(Object obj) {
return switch (obj) {
case Integer i when i > 0 -> "正整数";
case Integer i when i < 0 -> "负整数";
case Integer i -> "零";
case String s -> "字符串: " + s;
default -> "其他";
};
}
4. 序列化集合(Sequenced Collections)
新增有序集合接口,统一首尾元素访问和反转视图。
1
2
3
4
5
6
7
// 新接口:SequencedCollection, SequencedSet, SequencedMap
SequencedCollection<String> seq = new LinkedHashSet<>();
seq.addFirst("first");
seq.addLast("last");
String first = seq.getFirst();
String last = seq.getLast();
SequencedCollection<String> reversed = seq.reversed();
5. 字符串模板(预览)
在字符串中嵌入表达式,类型安全的字符串插值。
1
2
3
4
5
6
7
8
9
10
11
12
String name = "Java";
int version = 21;
String msg = STR."Hello \{name}, version \{version}!";
// "Hello Java, version 21!"
// 多行
String json = STR."""
{
"name": "\{name}",
"version": \{version}
}
""";
6. 匿名类和实例主方法(预览)
简化Java入门程序的编写。
1
2
3
4
5
6
7
8
9
10
11
// 传统写法
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello!");
}
}
// JDK 21 预览写法
void main() {
System.out.println("Hello!");
}
7. 未命名模式和变量(预览)
使用 _ 表示不需要的变量。
1
2
3
4
5
6
7
8
9
if (obj instanceof Point(int x, _)) {
// 只关心x坐标
}
try {
// ...
} catch (Exception _) {
// 不需要异常变量
}
8. 结构化并发(预览)
管理并发子任务的生命周期。
9. 作用域值(预览)
线程间安全共享不可变数据。
10. 其他
- 外部函数和内存API(第三次预览)
- Vector API(第六次孵化)
- 分代ZGC:引入年轻代/老年代分离收集,降低GC CPU和内存开销,
-XX:+UseZGC -XX:+ZGenerational - 密钥封装机制API
- 弃用 Windows 32位 x86 端口
- 准备禁止动态加载代理:影响APM工具和热部署工具,动态attach时发出警告
JDK 22(2024年3月)
1. Foreign Function & Memory API(正式)
JDK 22 将 FFM API 正式化,用标准 API 统一“调用本地函数 + 访问堆外内存”这两类能力,目标是逐步替代 JNI、Unsafe 与手写本地绑定代码。
- 使用
MemorySegment、Arena管理本地内存生命周期 - 使用
Linker、SymbolLookup绑定 C 函数 - 可读性、可维护性和安全性都优于传统 JNI
2. 未命名变量和模式(正式)
使用 _ 表示“这个变量存在,但值不会被使用”,能明显降低模式匹配、解构和异常处理中的样板代码。
1
2
3
4
5
6
7
8
9
if (obj instanceof Point(int x, _)) {
System.out.println(x);
}
try {
// ...
} catch (IOException _) {
// 只关心异常类型,不关心变量名
}
3. Stream Gatherers(预览)
Stream 新增可定制的中间操作扩展点,适合做窗口聚合、批量折叠、跨元素状态处理等过去很难优雅表达的流水线逻辑。
4. Class-File API(预览)
提供标准化的 class 文件解析、生成与转换 API,降低 ASM 这类第三方字节码库与 JDK 版本升级之间的耦合。
5. 其他
- 构造器支持
super(...)前置语句(预览) - 启动器支持多文件源码程序
- 结构化并发、Scoped Values 继续预览
- G1 Region Pinning:JNI critical region 场景下不再简单地整堆回退,降低 G1 的可预测停顿风险
JDK 23(2024年9月)
1. Markdown Documentation Comments
Javadoc 注释支持 Markdown,减少 HTML 标签噪音,文档书写体验更接近现代文档工具。
1
2
3
4
5
/// 返回用户信息。
///
/// - 参数 `id`:用户主键
/// - 返回值:查询到的用户对象
User findById(long id) { ... }
2. 模块导入声明(预览)
通过 import module ...; 简化模块化项目对常用模块的导入,降低 JPMS 在业务代码中的样板量。
3. ZGC 默认启用分代模式
JDK 23 并没有把 ZGC 变成默认 GC,而是把“启用 ZGC 之后默认使用分代模式”变成默认行为,对象晋升、代际回收和 CPU / 内存开销控制更符合现代服务端场景。
4. Primitive Types in Patterns / instanceof / switch(预览)
模式匹配开始覆盖原始类型,意味着 switch、instanceof 的统一抽象继续向前推进。
5. 其他
- Stream Gatherers、Class-File API、Structured Concurrency、Scoped Values 继续迭代
sun.misc.Unsafe的内存访问方法进入“准备移除”阶段- Simple Source Files / Instance Main Methods 再次预览
JDK 24(2025年3月)
1. Class-File API(正式)
字节码处理终于拥有标准库级别的稳定 API,对于框架、代理生成器、编译器插件和 AOT 工具链都很重要。
2. Stream Gatherers(正式)
Stream 从“常见中间操作集合”扩展到“可编排的中间操作框架”,对于复杂流式处理场景更友好。
3. 虚拟线程不再因 synchronized 直接固定载体线程
JDK 24 通过 JEP 491 改善了虚拟线程在监视器同步场景下的 pin 问题,减少了“代码语义没变,但吞吐突然上不去”的 Loom 使用门槛。
4. 紧凑对象头(实验)
紧凑对象头开始以实验特性进入 JDK,目标是压缩 64 位对象头开销,降低大规模对象分配场景的内存占用。
5. 其他
- Security Manager 永久禁用,只保留兼容外壳,实际上已经退出主流安全模型
- ZGC 移除非分代模式,分代成为唯一实现路线
- Ahead-of-Time Class Loading & Linking:把部分类加载和链接成本前移,优化启动路径
- Generational Shenandoah(实验):Shenandoah 开始引入分代能力
- 新增 ML-KEM / ML-DSA 等抗量子密码算法支持
JDK 25(2025年9月)⭐ LTS
1. Scoped Values(正式)
Scoped Values 在 JDK 25 正式化,给出比 ThreadLocal 更适合虚拟线程、更便于作用域管理的上下文传递模型。
- 值不可变,作用域边界清晰
- 与结构化并发协作更自然
- 更适合请求上下文、链路追踪、鉴权信息等只读共享数据
2. 模块导入声明(正式)
JPMS 继续朝“更容易写、而不是只强调强封装”演进,模块导入声明从预览转正,降低模块化工程的使用门槛。
3. Flexible Constructor Bodies(正式)
构造器可以在显式 super(...) 之前编写不依赖当前实例的语句,减少为了初始化顺序而拆辅助方法、拆中间构造器的样板写法。
4. Compact Source Files and Instance Main Methods(正式)
Java 入门程序进一步简化,但它并不只是“教学语法糖”,也意味着 Java 语言层开始更认真地处理小型脚本、示例代码和快速验证场景。
5. 紧凑对象头(正式)
JDK 24 还是实验特性的紧凑对象头,在 JDK 25 正式交付。对于对象密集型服务、缓存系统和高并发分配场景,这一变化直接影响堆内存利用率。
6. 分代 Shenandoah(正式)
Shenandoah 终于具备分代能力,意味着低延迟 GC 不再只有 ZGC 一条路线;在不同发行版和部署环境中,延迟优先型 GC 的选择空间更大。
7. 其他
- Structured Concurrency 仍处于第五次预览,并未在 JDK 25 正式化
- Key Derivation Function API 正式
- Stable Values 进入预览
- JFR CPU-Time Profiling / Cooperative Sampling / Method Timing & Tracing 持续增强
- AOT Command-Line Ergonomics / AOT Method Profiling 继续推进 Leyden 相关启动优化路线
JVM/GC 演进专题
以下按版本梳理 JVM 和垃圾收集器方面的重要演进,方便对比各版本在性能、内存管理上的变化。
JDK 5 JVM改进
- 类数据共享(CDS):将核心类的元数据存储为共享归档文件,多个JVM实例共享,减少启动时间和内存占用
- Ergonomics(自适应调优):JVM根据运行环境自动选择GC策略、堆大小等参数
- Server VM 默认化:在服务端环境下默认使用 Server VM(C2编译器),优化长时间运行的应用性能
- 并行GC成为默认收集器(Server模式):
-XX:+UseParallelGC - 64位 JVM 支持增强
JDK 6 JVM改进
- 锁优化三件套:
- 偏向锁(Biased Locking):无竞争时消除同步原语开销,对象头记录偏向线程ID
- 锁消除(Lock Elimination):JIT通过逃逸分析,消除不可能存在竞争的锁
- 锁粗化(Lock Coarsening):合并相邻的同步块,减少加锁/解锁次数
- 自适应自旋锁(Adaptive Spinning):根据历史自旋成功率动态调整自旋次数
- 逃逸分析(Escape Analysis):分析对象是否逃出方法/线程,支持栈上分配、标量替换
- 分层编译(Tiered Compilation,初步引入):结合C1(快速编译)和C2(深度优化)
- GC优化:Parallel GC吞吐量提升,CMS收集器稳定性增强
- JMX/JConsole增强:更好的运行时监控能力
- Native Memory Tracking 基础
JDK 7 JVM改进
- G1垃圾收集器(实验性引入):
- 面向大堆内存设计(>4GB),替代CMS的候选方案
- Region化内存布局:将堆划分为大小相等的Region(1MB~32MB)
- 混合收集(Mixed GC):同时回收年轻代和部分老年代Region
- 可预测的停顿时间目标:
-XX:MaxGCPauseMillis - 增量式并发标记
- invokedynamic 字节码指令:
- 新增第五种方法调用指令,支持动态语言高效运行在JVM上
- 为JDK8 Lambda表达式的实现提供基础
- 通过
MethodHandle和CallSite实现动态方法分派
- 压缩对象指针(Compressed Oops)默认开启:64位JVM中使用32位引用表示堆中对象,节省内存
- 分层编译默认开启:
-XX:+TieredCompilation - Fork/Join框架的work-stealing算法:充分利用多核CPU
JDK 8 JVM改进
- 永久代(PermGen)移除,引入元空间(Metaspace):
- 类元数据存储从JVM堆迁移到本地内存(Native Memory)
- 不再有
java.lang.OutOfMemoryError: PermGen space - 默认元空间大小仅受本地内存限制,可通过
-XX:MaxMetaspaceSize设置上限 -XX:MetaspaceSize设置初始阈值,超过后触发Full GC并自动调整- 字符串常量池从永久代移到堆中(实际在JDK7已移动)
- Lambda 的 JVM 实现:
- 使用
invokedynamic+LambdaMetafactory在运行时生成实现类 - 避免为每个Lambda生成匿名内部类文件,减少类加载开销
- 使用
- Nashorn引擎:基于
invokedynamic实现高性能JavaScript执行 - PermGen相关参数移除:
-XX:PermSize、-XX:MaxPermSize不再生效 - 默认GC:Parallel GC(吞吐量优先)
1
2
3
4
5
// JDK8 元空间相关JVM参数
-XX:MetaspaceSize=256m // 元空间初始阈值
-XX:MaxMetaspaceSize=512m // 元空间最大值
-XX:MinMetaspaceFreeRatio=40 // GC后最小空闲比例
-XX:MaxMetaspaceFreeRatio=70 // GC后最大空闲比例
JDK 9 JVM改进
- G1成为默认垃圾收集器:
- 替代Parallel GC成为默认GC:
-XX:+UseG1GC - String去重(String Deduplication):自动检测并去重堆中相同内容的String
- 并发标记周期优化
- 替代Parallel GC成为默认GC:
- 统一JVM日志框架(JEP 158):
- 所有GC日志、编译日志、类加载日志统一格式
-Xlog:gc*替代旧的-XX:+PrintGCDetails等参数- 支持日志轮转、标签过滤、多输出目标
- AOT编译(实验性,JEP 295):
jaotc工具将字节码预编译为本地代码- 减少JIT编译的预热时间
- Compact Strings(紧凑字符串):
- String内部从
char[]改为byte[]+ encoding flag - 纯Latin-1字符串内存占用减半
- String内部从
- 模块化对JVM的影响:
- 强封装JDK内部API
--add-opens、--add-exports参数控制模块可见性
- Indify String Concatenation:字符串拼接使用
invokedynamic优化
1
2
3
4
5
# JDK9+ 统一日志格式
java -Xlog:gc*:file=gc.log:time,uptime,level,tags:filecount=5,filesize=10m MyApp
# 旧参数(JDK9前)
java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log MyApp
JDK 10 JVM改进
- G1并行Full GC(JEP 307):
- 之前G1的Full GC使用单线程的Mark-Sweep-Compact算法
- 现在使用并行化的Full GC,显著降低Full GC停顿时间
- 应用程序类数据共享(AppCDS,JEP 310):
- 将CDS扩展到应用类路径上的类
- 多个JVM进程可共享应用类的元数据
- 加速启动时间10%~30%
- 实验性Java-Based JIT编译器(Graal,JEP 317):
- 用Java编写的JIT编译器
- 可替换C2编译器:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler - 为GraalVM和Native Image做基础
- 线程局部管控(Thread-Local Handshakes,JEP 312):
- 无需全局VM安全点即可对单个线程执行操作
- 减少不必要的全局停顿
- 堆分配在备用内存设备上(JEP 316):支持将堆放在NV-DIMM等非易失内存上
1
2
3
4
5
6
7
# AppCDS 使用步骤
# 1. 导出类列表
java -Xshare:off -XX:DumpLoadedClassList=classes.lst -jar app.jar
# 2. 创建共享归档
java -Xshare:dump -XX:SharedClassListFile=classes.lst -XX:SharedArchiveFile=app.jsa -jar app.jar
# 3. 使用共享归档启动
java -Xshare:on -XX:SharedArchiveFile=app.jsa -jar app.jar
JDK 11 JVM改进
- ZGC(实验性,JEP 333):
- 可伸缩的低延迟垃圾收集器
- 停顿时间不超过10ms,且不随堆大小增长
- 支持TB级别堆内存(8MB ~ 16TB)
- 并发执行所有昂贵操作(标记、重定位、引用处理)
- 使用着色指针(Colored Pointers)和读屏障(Load Barriers)
- 启用:
-XX:+UnlockExperimentalVMOptions -XX:+UseZGC
- Epsilon GC(JEP 318):
- No-Op垃圾收集器,不回收任何内存
- 适用于性能测试、极短生命周期应用、内存压力测试
- 堆耗尽时直接OOM
- 启用:
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
- 飞行记录器(JFR,JEP 328)开源:
- 之前是商业特性,JDK11开源
- 低开销(<2%)的性能数据采集框架
- 记录GC事件、线程活动、IO操作、锁竞争等
- 启用:
-XX:StartFlightRecording=duration=60s,filename=recording.jfr
- 嵌套类访问控制(Nest-Based Access Control,JEP 181):
- 内部类和外部类之间的私有成员访问不再需要编译器生成桥接方法
- 减少类文件大小,简化访问逻辑
- 动态类文件常量(JEP 309):新增
CONSTANT_Dynamic常量池条目 - 低开销堆分析(JEP 331):通过JVMTI采样分析堆分配
1
2
3
4
5
6
7
8
9
# ZGC 常用参数
-XX:+UseZGC
-XX:ZCollectionInterval=5 # GC触发间隔(秒)
-XX:ZAllocationSpikeTolerance=2 # 分配速率容忍度
-Xmx16g # 堆最大值
# JFR 使用
java -XX:StartFlightRecording=settings=profile,duration=60s,filename=app.jfr -jar app.jar
jfr print --events jdk.GCHeapSummary app.jfr
JDK 12 JVM改进
- Shenandoah GC(实验性,JEP 189):
- 由Red Hat开发的低暂停时间GC
- 通过与应用线程并发执行压缩来减少停顿时间
- 停顿时间与堆大小无关
- 使用Brooks指针实现并发对象移动
- 与ZGC的区别:Shenandoah使用转发指针+写屏障,ZGC使用着色指针+读屏障
- G1优化:
- 可中止的混合收集(JEP 344):将Mixed GC拆分为可选和必须两部分,超时可中止
- 及时归还未使用内存(JEP 346):G1在空闲时自动将Java堆内存归还操作系统
- 默认CDS归档(JEP 341):JDK安装时自动生成默认的类数据共享归档
- 微基准测试套件(JEP 230):集成JMH,方便JDK开发者编写性能测试
JDK 13 JVM改进
- ZGC归还未使用内存(JEP 351):
- ZGC将不再使用的堆内存归还给操作系统
- 类似G1在JDK12中的改进
- 对容器化环境特别有意义(减少内存计费)
- 动态CDS归档(JEP 350):
- 在应用退出时自动创建CDS归档
- 简化AppCDS的使用流程:
-XX:ArchiveClassesAtExit=app.jsa - 无需手动执行三步操作
- 重新实现旧版Socket API(JEP 353):
- 使用更现代的 NIO 实现替换老的 PlainSocketImpl
- 便于支持虚拟线程(Project Loom准备工作)
JDK 14 JVM改进
- 有帮助的NullPointerException(JEP 358):
- JVM精确描述哪个变量为null
- 需要
-XX:+ShowCodeDetailsInExceptionMessages启用(JDK15默认开启) - 通过分析字节码确定null位置
- 移除CMS垃圾收集器(JEP 363):
- CMS(Concurrent Mark Sweep)在JDK9标记为废弃,JDK14正式移除
- 使用
-XX:+UseConcMarkSweepGC将报错 - 推荐迁移到G1或ZGC
- ZGC支持macOS和Windows(JEP 364/365):之前仅Linux
- 废弃 ParallelScavenge + SerialOld GC组合(JEP 366)
- 外部内存访问API(孵化,JEP 370):安全高效地访问堆外内存
- JFR事件流(JEP 349):支持实时消费JFR事件,无需落盘
JDK 15 JVM改进
- ZGC正式发布(JEP 377):
- 从实验性变为生产可用
- 启用参数简化为:
-XX:+UseZGC(无需UnlockExperimentalVMOptions) - 支持类卸载、NUMA感知、并发根处理
- Shenandoah GC正式发布(JEP 379):
- 启用:
-XX:+UseShenandoahGC
- 启用:
- 废弃并禁用偏向锁(JEP 374):
- 偏向锁在现代多核处理器和高并发场景下带来的收益减少
- 偏向锁撤销的性能开销高昂
- 默认禁用:
-XX:-UseBiasedLocking - 准备后续版本移除
- 隐藏类(JEP 371):
- 供框架在运行时生成的类,不可被发现(不能通过名称引用)
- 替代
Unsafe.defineAnonymousClass() - 支持GC回收,减少元空间压力
- 重新实现DatagramSocket API(JEP 373)
JDK 16 JVM改进
- ZGC并发线程栈处理(JEP 376):
- 将线程栈处理从安全点移到并发阶段
- 进一步降低GC停顿时间(从几ms降到<1ms)
- 消除ZGC停顿时间与线程数量的正比关系
- 弹性元空间(JEP 387):
- 更及时地将未使用的类元数据内存归还操作系统
- 减少元空间内存碎片
- 减少类加载器内存占用
- 默认强封装JDK内部API(JEP 396):
--illegal-access=deny成为默认值- 非法反射访问内部API将抛出异常
- 需要显式使用
--add-opens放开
- Unix域套接字(JEP 380):同一主机进程间高效通信
- Vector API(孵化,JEP 338):利用SIMD指令加速向量计算
JDK 17 JVM改进
- 移除实验性AOT和JIT编译器(JEP 410):
- 移除
jaotcAOT编译工具 - 移除基于Graal的JIT编译器(但Graal仍可作为独立项目使用)
- 保留JVMCI接口,第三方JIT仍可接入
- 移除
- 强封装JDK内部API(JEP 403):
- 移除
--illegal-access命令行选项 - 除少数关键内部API外(如
sun.misc.Unsafe),全部不可访问
- 移除
- 废弃Security Manager(JEP 411):准备后续移除
- 恢复始终严格的浮点语义(JEP 306):
- 所有浮点运算始终使用strict模式
strictfp关键字变为默认行为(不再需要显式声明)
- 上下文特定的反序列化过滤器(JEP 415):增强安全性
- macOS/AArch64端口(JEP 391):原生支持Apple M1芯片
JDK 18 JVM改进
- 废弃Finalization(JEP 421):
Object.finalize()标记为废弃- Finalizer线程带来不确定性和性能问题
- 推荐使用
Cleaner和try-with-resources替代 - 可通过
--finalization=disabled提前禁用
- 方法句柄重新实现反射核心(JEP 416):
- 减少维护成本,统一底层实现
- 反射调用性能提升
JDK 19 JVM改进
- 虚拟线程(预览,JEP 425)对JVM的影响:
- 虚拟线程不绑定OS线程,由JVM调度
- 栈帧存储在堆中,可以暂停和恢复
- 载体线程(Carrier Thread)池管理物理线程
- 针对阻塞操作的优化:阻塞时自动切换虚拟线程
- 与现有同步API完全兼容
- 结构化并发(孵化):配合虚拟线程管理任务生命周期
- 外部函数和内存API(预览,JEP 424):替代JNI和Unsafe的安全API
JDK 20 JVM改进
- 作用域值(Scoped Values,孵化,JEP 429):
- 替代
ThreadLocal的更高效方案 - 不可变,自动清理,虚拟线程友好
- 无内存泄漏风险(vs ThreadLocal需要手动remove)
- 替代
- 虚拟线程持续改进:减少pin(固定)场景
- Vector API持续孵化
JDK 21 JVM改进
- 分代ZGC(JEP 439):
- ZGC引入分代架构:年轻代和老年代分开收集
- 年轻对象收集频率更高,利用「大多数对象朝生夕死」的特性
- 降低GC所需的CPU和内存开销
- 进一步降低分配停顿风险
- 启用:
-XX:+UseZGC -XX:+ZGenerational
- 虚拟线程正式发布(JEP 444)对JVM的意义:
- JVM线程模型重大变革:M:N线程模型
- 一个OS线程可承载数十万虚拟线程
synchronized块内的虚拟线程会被pin到载体线程(建议使用ReentrantLock)- JFR/JMX完全支持虚拟线程监控
- 线程dump支持虚拟线程(JSON格式):
jcmd <pid> Thread.dump_to_file -format=json file.json
- 准备禁止动态加载代理(JEP 451):
- 动态attach Agent时发出警告
- 后续版本将默认禁止(需要显式允许)
- 影响部分APM工具和热部署工具
- 密钥封装机制API(JEP 452):标准化KEM加密操作
1
2
3
4
5
# JDK21 分代ZGC
java -XX:+UseZGC -XX:+ZGenerational -Xmx4g -jar app.jar
# 虚拟线程线程dump
jcmd <pid> Thread.dump_to_file -format=json threads.json
JDK 22 JVM改进
- G1 Region Pinning(JEP 423):
- JNI critical region 场景下,G1 不再因为对象被 pin 住就大范围失去回收能力
- 更适合混合使用 Java 与本地库的服务
- FFM API 正式(JEP 454):
- 让“本地函数调用 + 堆外内存访问”逐步走向标准化
- 从长期看,会持续削弱 JNI /
Unsafe在业务层的存在感
- Class-File API 预览(JEP 457):
- 字节码工具链开始拥有标准 API
- 对框架代理、字节码增强、AOT 工具都很关键
JDK 23 JVM改进
- ZGC 默认启用分代模式(JEP 474):
- 这里的“默认”是指启用
-XX:+UseZGC后默认进入分代实现 - 不是说 JDK 23 的默认 GC 从 G1 变成了 ZGC
- 这里的“默认”是指启用
sun.misc.Unsafe内存访问方法准备移除(JEP 471):- 继续推动标准 API 替代内部能力
- 对依赖底层内存操作的中间件、序列化框架影响较大
JDK 24 JVM改进
- 虚拟线程去 pin 化(JEP 491):
synchronized不再天然把虚拟线程固定到载体线程- Loom 在传统同步代码中的可用性明显提升
- ZGC 移除非分代模式(JEP 490):
- 分代不再只是增强项,而是 ZGC 的唯一实现方向
- Generational Shenandoah(JEP 404,实验):
- 低延迟 GC 阵营开始同时具备 ZGC 和 Shenandoah 两条分代路线
- 紧凑对象头(JEP 450,实验):
- 对象头压缩开始进入可验证阶段
- AOT Class Loading & Linking(JEP 483):
- 为后续更激进的启动优化和 CDS / Leyden 路线打基础
JDK 25 JVM改进
- Scoped Values 正式(JEP 506):
- 虚拟线程时代的上下文传递模型趋于稳定
- 与结构化并发、不可变上下文共享更契合
- 紧凑对象头正式(JEP 519):
- 64 位对象模型的内存开销进一步下降
- 对缓存、对象池、海量短命对象分配场景有直接价值
- 分代 Shenandoah 正式(JEP 521):
- 说明“分代 + 低延迟”已经成为现代 GC 的共同演进方向
- JFR 持续增强(JEP 509 / 518 / 520):
- CPU 时间剖析、协作式采样、方法级计时与追踪能力更完整
- AOT 启动优化继续前移(JEP 514 / 515):
- 进一步强化“把启动期开销前移到构建或预热阶段”的路线