Java垃圾回收的五十年——从标记清除到ZGC的演进之路

简介: 垃圾回收是Java平台的标志性特性,也是无数开发者选择Java而非C++的重要原因。

垃圾回收是Java平台的标志性特性,也是无数开发者选择Java而非C++的重要原因。从JDK 1.0到JDK 21,Java的垃圾回收算法经历了翻天覆地的变化,每一次演进都在吞吐量、延迟和内存占用之间寻找新的平衡。理解不同垃圾回收器的特点和工作原理,对于调优Java应用性能至关重要。
参考:https://xbivx.cn/category/provincial-forecast.html

标记-清除算法是最基础的垃圾回收算法。它分为两个阶段:标记阶段遍历所有存活对象,清除阶段回收未被标记的对象。这种算法的缺点是产生内存碎片,以及暂停时间与堆大小成正比。标记-清除的变种——标记-复制算法将内存分为两个半区,每次只使用其中一个,回收时将存活对象复制到另一个半区,然后清空原半区。复制算法无碎片,但内存利用率低。标记-整理算法在标记之后将存活对象向一端移动,然后清理边界以外的内存,既消除了碎片,又提高了内存利用率,但移动对象的开销较大。

分代假说是Java垃圾回收设计的理论基础。该假说指出:大部分对象朝生夕灭(年轻代),而老年代中的对象则长期存活。基于这个假说,JVM将堆内存分为年轻代和老年代。年轻代使用复制算法(因为大部分对象在GC中死亡),老年代使用标记-清除或标记-整理算法(因为存活率高,复制成本大)。

Serial GC是最古老的垃圾回收器,使用单线程进行垃圾回收。它会触发"Stop-The-World"暂停,所有应用线程停止,直到GC完成。Serial GC适合客户端应用或单处理器环境,堆内存较小(几十MB到几百MB)。它的优点是简单、内存占用低、没有线程同步开销。

Parallel GC(也称为吞吐量优先收集器)是JDK 8及之前版本的默认收集器。它使用多线程进行垃圾回收,充分利用多核CPU。Parallel GC的目标是最大化吞吐量(应用运行时间与总时间的比值)。它适用于后台处理、批处理等对暂停时间不敏感的场景。Parallel GC在年轻代使用并行复制,在老年代使用并行标记-整理。

CMS GC(Concurrent Mark Sweep)是第一款低延迟垃圾回收器。它的目标是减少暂停时间,将垃圾回收的大部分工作与应用线程并发执行。CMS的回收过程包括:初始标记(STW,标记GC Roots直接可达的对象)、并发标记(与应用线程一起标记所有存活对象)、重新标记(STW,处理并发标记期间发生变化的对象)、并发清除(清除未标记的对象)。CMS的缺点是产生内存碎片(因为不整理),且浮动垃圾(并发标记期间新产生的垃圾)需要等待下次GC。

G1 GC(Garbage First)在JDK 7u4中正式发布,在JDK 9中成为默认收集器。G1将堆内存划分为多个大小相等的Region,每个Region可以是年轻代或老年代。G1的回收策略是:优先回收垃圾最多的Region(Garbage First因此得名)。G1的目标是在可预测的暂停时间内回收尽可能多的内存。它使用停顿预测模型,动态调整年轻代大小和回收区域的数量。G1的回收过程包括:年轻代收集、并发标记周期、混合收集(逐步回收老年代Region)。G1避免了CMS的碎片问题,因为它在需要时对Region进行整理。
参考:https://xbivx.cn/category/national-weather.html

ZGC(Z Garbage Collector)在JDK 11中引入,在JDK 15中成为生产就绪。ZGC的目标是在任意堆大小(从几百MB到16TB)下,将暂停时间控制在10ms以内。ZGC使用读屏障和染色指针技术,将大部分GC工作与应用线程并发执行。ZGC的暂停只发生在根扫描阶段,且暂停时间不随堆大小增长。ZGC的设计挑战包括:处理大堆的并发标记和重定位、与操作系统内存管理的交互、以及JIT编译器的适配。ZGC适用于大堆内存、低延迟的场景,如金融交易系统、在线游戏服务器。

Shenandoah GC与ZGC类似,也是低延迟并发回收器,由Red Hat开发,在JDK 12中引入。与ZGC使用染色指针不同,Shenandoah使用 Brooks指针(转发指针)和读屏障实现并发压缩。Shenandoah的回收过程包括:初始标记、并发标记、并发清理、并发压缩等阶段。Shenandoah和ZGC代表了垃圾回收技术的前沿,它们将暂停时间从秒级降低到毫秒级甚至亚毫秒级。

Epsilon GC是JDK 11中引入的无操作垃圾回收器。它分配内存但不回收,当堆内存耗尽时JVM退出。Epsilon适用于短期任务、性能测试、或完全由应用管理内存的场景。

GC调优是Java性能工程的重要部分。调优的步骤包括:明确目标(吞吐量优先还是延迟优先)、监控GC日志(使用-Xlog:gc*)、选择合适的垃圾回收器、调整堆大小(-Xms和-Xmx)、调整年轻代与老年代比例(-XX:NewRatio)、调整晋升阈值(-XX:MaxTenuringThreshold)等。过度调优往往是反模式——在大多数情况下,默认配置已经足够好。

GC日志分析工具可以帮助理解GC行为。GCViewer、GCEasy、JMC等工具可以可视化GC事件,分析暂停时间、吞吐量、晋升速率等指标。现代JVM还提供了JFR(Java Flight Recorder)事件,可以低开销地采集GC信息。

未来趋势:Project Lilliput(JDK 21预览)尝试缩减对象头大小,减少内存占用;Project Valhalla的值类型将进一步减少对象数量,降低GC压力;分代ZGC(JDK 21正式)将年轻代和老年代分离,进一步提升ZGC的性能。

垃圾回收不是魔法,而是一套精心设计的算法和工程实现。理解GC的工作原理,不仅有助于调优,还能帮助开发者写出对GC友好的代码:避免对象晋升、避免大对象分配、使用对象池复用对象、以及及时释放引用。
参考:https://xbivx.cn

目录
相关文章
|
缓存 负载均衡 监控
Dubbo简介
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册)
696 0
Dubbo简介
|
4月前
|
人工智能 运维 云计算
我做了一个 Loki AI 事故分析引擎,已上架阿里云计算巢
后端开发者Luke打造Loki AI事故分析引擎,已上架阿里云计算巢!支持自动拉取Loki日志、调用Qwen/DeepSeek大模型智能根因分析,1-2分钟生成结构化报告(含根因、建议、时间线等),并推送至企微/钉钉。私有化部署,数据不出阿里云账号。
637 3
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
1380 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
SQL XML Java
MyBatis-Plus多表关联查询
MyBatis-Plus多表关联查询
2673 0
|
人工智能 供应链 API
2026:深度拆解智能体(Agent)重构西南制造的三重核心能力
2026年,中国制造业重心西移,西南工厂面临供应链与人力双重挑战。智能体(Agent)正以感知、推理、行动三位一体能力,推动生产从“经验驱动”迈向“自主决策”。它不仅是技术升级,更是认知革命——重构调度、工艺与供应链,实现毫秒响应、知识沉淀与跨域协同,打造高“认知密度”的未来工厂。
344 0
|
缓存 小程序 IDE
【每周一个小技巧】支付宝小程序自定义tabbar效果
【每周一个小技巧】支付宝小程序自定义tabbar效果
948 2
|
机器学习/深度学习 算法 Java
大牛用十年功力带你彻底理解JVM垃圾回收器:ZGC,回收设计
ZGC的并发回收算法采用的也是“目的空间不变性”的设计,关于目的空间不变性的更多内容可以参考第7章。 在第7章中提到,Shenandoah从JDK 13开始也采用“目的空间不变性”的设计。但是ZGC与Shenandoah相比,还是有不少细节并不相同,如表8-3所示。
|
4月前
|
存储 算法 Java
Java的垃圾回收算法演进:从Serial到ZGC
Java的自动内存管理(垃圾回收,GC)是其区别于C++的重要特性之一。
393 3
|
Java 关系型数据库 数据库连接
SpringBoot项目使用yml文件链接数据库异常
【10月更文挑战第3天】Spring Boot项目中数据库连接问题可能源于配置错误或依赖缺失。YAML配置文件的格式不正确,如缩进错误,会导致解析失败;而数据库驱动不匹配、连接字符串或认证信息错误同样引发连接异常。解决方法包括检查并修正YAML格式,确认配置属性无误,以及添加正确的数据库驱动依赖。利用日志记录和异常信息分析可辅助问题排查。
1648 11
|
存储 Java Linux
什么? ZGC在Java 17中没有更新了!yyds
Java长期支持版本Java11发布时推出了ZGC, 之后的Java12 -16均有ZGC的一些更新。然而Java17的新特性已经敲定,确定没有关于ZGC的相关更新,也从另一方面说明了至Java17 ZGC已经比较稳定,可以作为比较稳定的GC垃圾回收器。相信未来ZGC必定会成为主流的Java垃圾回收期,那么盘一盘ZGC就是必然的了。
什么? ZGC在Java 17中没有更新了!yyds

热门文章

最新文章