从 Java 1 到 Java 25 的垃圾回收器演进与优化全解析
| Java版本 | 新特性/增强内容 |
|---|---|
| Java 1 | 引入 Serial 垃圾收集器,单线程垃圾回收实现 |
| Java 2 | 引入 Parallel Scavenge 收集器(吞吐量优先) |
| Java 3 | 引入 Parallel Old 收集器 |
| Java 4 | Parallel Scavenge 收集器正式发布 |
| Java 4 | 引入 NIO(New I/O),提高 I/O 操作效率,间接减少 GC 压力 |
| Java 5 | 引入 CMS(Concurrent Mark Sweep)收集器,实现低延迟垃圾回收 |
| Java 5 | 引入 Generational Garbage Collection(分代垃圾回收)概念 |
| Java 6 | 对 CMS 和 Parallel 收集器进行性能优化 |
| Java 7 | 引入 G1(Garbage-First)垃圾收集器(实验性) |
| Java 7 | 引入 invokedynamic 指令,为动态类型语言提供更好支持,优化对象创建性能 |
| Java 7 | 引入 NIO.2(AIO),提升 I/O 操作性能,减少 GC 压力 |
| Java 8 | JEP 173: 移除一些很少使用的垃圾回收器组合 |
| Java 8 | JEP 180: 使用平衡树处理频繁的 HashMap 碰撞 |
| Java 9 | JEP 248: 使 G1 成为默认垃圾收集器 |
| Java 9 | JEP 250: 在 CDS 归档中存储内部字符串 |
| Java 10 | JEP 307: G1 的并行全垃圾回收 |
| Java 10 | JEP 310: 应用程序类数据共享 |
| Java 11 | JEP 318: Epsilon 垃圾回收器(实验性) |
| Java 11 | JEP 320: 移除 Java EE 和 CORBA 模块(包括相关垃圾回收器) |
| Java 11 | JEP 321: HTTP Client(标准化) |
| Java 12 | JEP 189: Shenandoah 垃圾收集器(预览特性) |
| Java 12 | JEP 344: G1 的可中止混合收集 |
| Java 12 | JEP 346: G1 及时返回未使用的已提交内存 |
| Java 15 | JEP 377: ZGC 转正为生产就绪功能 |
| Java 16 | JEP 376: ZGC:并发线程栈处理 |
| Java 17 | JEP 387: 弹性元空间 |
| Java 21 | JEP 439: 分代式 ZGC |
| Java 25 | JEP 519: 紧凑对象头 |
功能详细介绍
1. Java 1 - 垃圾回收的起点
Java 1.0 引入了最基本的垃圾回收机制,为后续发展奠定了基础。
Serial 垃圾收集器
引入了 Serial 垃圾收集器,这是最基础的单线程垃圾回收实现。它使用简单的标记-清除-整理算法,适用于小型应用程序和客户端应用。
特点:
- 单线程执行:垃圾回收过程使用单个线程完成
- 简单高效:对于小堆内存应用,Serial GC 表现良好
- 暂停所有应用线程:在执行垃圾回收时会暂停所有应用程序线程(Stop-The-World)
2. Java 2 - 吞吐量优先的收集器
Java 2 在垃圾回收方面进行了重要改进,引入了新的收集器。
Parallel Scavenge 收集器(吞吐量优先)
引入了 Parallel Scavenge 收集器,这是一种关注吞吐量的新生代收集器。它通过并行化垃圾回收操作来提高整体性能。
优势:
- 多线程并行处理:利用多核处理器提高垃圾回收效率
- 吞吐量优先:专注于最大化应用程序的运行时间比例
- 可控制的停顿时间:可以通过参数调整期望的停顿时间
3. Java 3 - 老年代并行收集
Java 3 完善了并行收集器家族,为老年代提供了并行处理能力。
Parallel Old 收集器
引入了 Parallel Old 收集器,这是 Parallel Scavenge 收集器的老年代版本。它使用并行标记-整理算法处理老年代的垃圾回收。
特点:
- 与 Parallel Scavenge 配合:与新生代的 Parallel Scavenge 收集器形成完整的并行收集器组合
- 并行标记-整理:在老年代使用并行化的方式进行标记和整理操作
- 适用于大堆应用:特别适合需要高吞吐量的大堆内存应用
4. Java 4 - 并行收集器正式发布和 I/O 优化
Java 4 正式发布了 Parallel Scavenge 收集器,并引入了新的 I/O 技术。
Parallel Scavenge 收集器正式发布
Parallel Scavenge 收集器从实验性功能转为正式发布,成为生产环境可用的垃圾回收器。
NIO(New I/O)引入
引入了 NIO(New I/O),通过通道和缓冲区机制提高 I/O 操作效率,间接减少了 GC 压力。
优势:
- 减少对象创建:NIO 减少了传统 I/O 中临时对象的创建
- 提高 I/O 性能:通过内存映射文件等技术提高 I/O 操作性能
- 降低 GC 频率:减少了因 I/O 操作产生的垃圾,降低了垃圾回收频率
5. Java 5 - 并发收集器和分代回收概念
Java 5 是垃圾回收发展的重要里程碑,引入了并发收集器和分代回收概念。
CMS(Concurrent Mark Sweep)收集器
引入了 CMS(Concurrent Mark Sweep)收集器,这是一种以最短回收停顿时间为目标的收集器。
主要特性:
- 并发收集:大部分收集过程与应用程序线程并发执行
- 低停顿时间:通过并发执行减少应用程序暂停时间
- 基于标记-清除算法:使用标记-清除算法,避免内存整理的停顿
适用场景:
- 重视服务响应速度的应用
- 希望减少垃圾回收停顿时间的场景
Generational Garbage Collection(分代垃圾回收)概念
正式引入分代垃圾回收概念,将堆内存划分为不同代(年轻代和老年代),并针对不同代的特点采用不同的垃圾回收策略。
核心思想:
- 对象年龄分布:大部分对象都是朝生夕灭的
- 分区处理:将堆内存划分为不同区域,分别采用最适合的回收算法
- 提高回收效率:根据不同代的特点优化回收策略
6. Java 6 - 收集器性能优化
Java 6 主要对现有收集器进行了性能优化和稳定性提升。
CMS 和 Parallel 收集器性能优化
对 CMS 和 Parallel 系列收集器进行了多项性能优化,包括:
优化内容:
- 算法改进:优化了收集器内部算法,提高执行效率
- 内存管理:改进了内存分配和回收策略
- 并发处理:提升了并发处理能力,减少与应用线程的冲突
7. Java 7 - G1 收集器引入和性能增强
Java 7 引入了革命性的 G1 收集器,并增强了对象创建性能。
G1(Garbage-First)垃圾收集器(实验性)
引入了 G1(Garbage-First)垃圾收集器作为实验性功能。G1 是一款面向服务端应用的垃圾收集器,旨在替代 CMS 收集器。
核心特性:
- 区域化堆内存:将堆划分为多个大小相等的区域(Region)
- 优先回收:优先回收垃圾最多的区域,实现高效回收
- 可预测停顿:可以建立可预测的停顿时间模型
invokedynamic 指令
引入 invokedynamic 指令,为动态类型语言提供更好支持,同时优化了对象创建性能。
影响:
- 动态语言支持:为 JRuby、Jython 等动态语言提供性能基础
- 对象创建优化:优化了某些场景下的对象创建性能
- 减少 GC 压力:通过优化对象创建减少垃圾产生
NIO.2(AIO)
引入 NIO.2(异步 I/O),进一步提升 I/O 操作性能,减少 GC 压力。
优势:
- 异步操作:支持真正的异步 I/O 操作
- 减少资源消耗:通过异步处理减少线程和对象的创建
- 提升整体性能:改善了 I/O 密集型应用的性能表现
Java 8 - 垃圾回收基础增强
Java 8 在垃圾回收方面进行了多项改进,为后续版本的发展奠定了基础。
JEP 173: 移除一些很少使用的垃圾回收器组合
简化了 JVM 的垃圾回收配置选项,移除了一些很少使用的垃圾回收器组合,有助于减少开发者的配置负担,提高垃圾回收的效率。
JEP 180: 使用平衡树处理频繁的 HashMap 碰撞
改进了 HashMap 的实现,当发生频繁的碰撞时,使用平衡树而不是链表来存储元素。这提高了 HashMap 在高碰撞情况下的性能,减少了垃圾回收的压力。
2. Java 9 - G1 成为默认垃圾收集器
Java 9 在垃圾回收方面最重要的变化是将 G1 垃圾收集器设为默认选择。
JEP 248: 使 G1 成为默认垃圾收集器
G1(Garbage-First)垃圾收集器是一种面向服务器的垃圾收集器,旨在平衡吞吐量和低延迟。它通过将堆划分为多个区域,并优先回收垃圾最多的区域来实现高效的垃圾回收。
优势:
- 可预测的停顿时间:G1 能够满足用户设定的停顿时间目标
- 高吞吐量:在满足停顿时间目标的同时保持高吞吐量
- 大堆支持:特别适用于大内存堆的应用程序
JEP 250: 在 CDS 归档中存储内部字符串
在类数据共享(CDS)归档中存储内部字符串,减少了应用程序启动时间,间接改善了垃圾回收的性能。
3. Java 10 - G1 垃圾回收器增强
Java 10 继续优化 G1 垃圾收集器,提升其性能。
JEP 307: G1 的并行全垃圾回收
G1 的并行全垃圾回收功能通过利用多核处理器的优势,并行执行全垃圾回收任务,从而减少了停顿时间,提高了应用程序的响应速度。
在传统的 G1 实现中,全垃圾回收阶段是串行执行的,这可能会导致较长的停顿时间。JEP 307 通过并行化全垃圾回收操作,显著改善了这一问题。
JEP 310: 应用程序类数据共享
扩展了类数据共享(CDS)的功能,引入了应用程序类数据共享(AppCDS),允许开发者将自定义的应用程序类添加到共享存档中,进一步提高了应用程序的启动性能和内存使用效率。
4. Java 11 - 新垃圾回收器引入
Java 11 引入了新的垃圾回收器,扩展了垃圾回收的选择。
JEP 318: Epsilon 垃圾回收器(实验性)
Epsilon 是一种无操作垃圾收集器,它不执行实际的垃圾回收操作。该特性主要用于性能测试和内存压力测试等场景。
使用场景:
- 性能测试:避免垃圾回收对性能测试的干扰
- 内存压力测试:观察应用程序在没有垃圾回收的情况下的内存增长趋势
- 极短生命周期应用:对于运行时间很短的应用,可能不需要垃圾回收
5. Java 12 - Shenandoah 垃圾收集器引入
Java 12 引入了 Shenandoah 垃圾收集器作为预览特性。
JEP 189: Shenandoah 垃圾收集器(预览特性)
Shenandoah 是一个专门用来处理大堆和低延迟的垃圾收集器。它使用了一种用于并发压缩堆时维护对象引用的技术(Brooks Pointers),允许收集器在压缩堆时并行地移动对象,而不必暂停应用线程。
主要优势:
- 显著减少停顿时间:可以在应用运行时并行地进行垃圾回收
- 适用于大内存应用:对拥有大量内存的应用程序提供更平滑的性能表现
JEP 344: G1 的可中止混合收集
改进了 G1 垃圾收集器的混合收集过程,使其可以在收集过程中根据需要中止,以减少对应用程序的影响。
JEP 346: G1 及时返回未使用的已提交内存
改进了 G1 垃圾收集器的内存管理机制,使其能够及时返回未使用的已提交内存给操作系统,减少 JVM 的内存占用。
6. Java 15 - ZGC 转正
Java 15 将 ZGC 从实验性功能转正为生产就绪功能。
JEP 377: ZGC 转正为生产就绪功能
ZGC(Z Garbage Collector)是一种低延迟垃圾回收器,旨在实现毫秒级的垃圾回收停顿时间,即使在 TB 级别的堆上也是如此。
主要特性:
- 超低停顿时间:目标是将停顿时间控制在 10ms 以内
- 大堆支持:支持 TB 级别的堆大小
- 并发执行:大部分垃圾回收工作与应用程序线程并发执行
7. Java 16 - ZGC 增强
Java 16 继续增强 ZGC 的功能。
JEP 376: ZGC:并发线程栈处理
增强了 ZGC 的功能,使其能够并发地处理线程栈。在传统的垃圾回收过程中,线程栈的处理通常需要暂停应用程序线程,而 ZGC 的并发线程栈处理技术允许垃圾回收器在应用程序线程继续运行的同时,对线程栈进行扫描和更新引用。
8. Java 17 - 内存管理优化
Java 17 在内存管理方面进行了多项优化。
JEP 387: 弹性元空间
引入了弹性元空间机制,能够根据应用程序的运行时需求动态地调整元空间的大小。当应用程序加载的类增多时,弹性元空间可以自动扩展;而当一些类被卸载时,元空间又可以自动收缩。
9. Java 21 - 分代 ZGC
Java 21 引入了分代式 ZGC,进一步优化了 ZGC 的性能。
JEP 439: 分代式 ZGC
分代式 ZGC 结合了分代收集和 ZGC 垃圾回收器的优点。分代收集将堆内存分为不同的代(如年轻代和老年代),并针对不同代的特点采用不同的垃圾回收策略。ZGC 则是一种并发式垃圾回收器,旨在减少垃圾回收的停顿时间。
10. Java 25 - 对象头优化
Java 25 引入了紧凑对象头,优化了内存使用。
JEP 519: 紧凑对象头
通过减少对象头大小(从 12 字节到 8 字节),节省内存并提升性能:
性能影响:
- 堆使用减少 22%
- 执行速度提升 8%
- 垃圾收集频率降低 15%
垃圾回收器对比总结
| 垃圾回收器 | 引入版本 | 主要特点 | 适用场景 |
|---|---|---|---|
| Serial | Java 1 | 单线程,简单高效 | 小型应用,客户端应用 |
| Parallel | Java 4 | 多线程,并行处理 | 吞吐量优先的应用 |
| CMS | Java 5 | 低延迟,并发收集 | 响应时间敏感的应用 |
| G1 | Java 7 | 可预测停顿时间 | 大堆应用,平衡吞吐量和延迟 |
| ZGC | Java 11 | 毫秒级停顿时间 | TB级堆,极低延迟要求 |
| Epsilon | Java 11 | 无垃圾回收 | 性能测试,短生命周期应用 |
| Shenandoah | Java 12 | 超低停顿时间 | 超大堆,极低延迟要求 |
最佳实践建议
-
选择合适的垃圾回收器:
- 小型应用:Serial GC
- 吞吐量优先:Parallel GC
- 延迟敏感:G1 GC 或 ZGC
- 超大堆:Shenandoah 或 ZGC
-
合理配置堆大小:
- 根据应用需求设置初始堆和最大堆
- 避免堆大小频繁调整
-
监控和调优:
- 使用 JVM 监控工具观察垃圾回收行为
- 根据应用特点调整垃圾回收器参数
-
利用新特性:
- 使用 CDS 减少启动时间
- 合理使用弹性元空间
总结
从 Java 1 到 Java 25,Java 平台在垃圾回收方面持续演进,不断引入新的垃圾回收器和优化现有功能。这些改进不仅提升了垃圾回收的性能和效率,还为开发者提供了更多选择来满足不同应用场景的需求。随着硬件的发展和应用需求的变化,Java 的垃圾回收技术也在不断适应新的挑战,为现代应用程序提供更好的性能和更低的延迟。
更多推荐


所有评论(0)