4. 垃圾回收机制(GC)

news/2025/12/6 16:43:45/文章来源:https://www.cnblogs.com/hzsblog/p/19316139

本文内容基于个人对特定技术的理解和实践,或为对相关技术内容的整理与分享。请读者批判性阅读,如有疏漏或不准确之处,恳请斧正。

垃圾回收机制 (Garbage Collection - GC)

Heap与Method Area 内存中的死亡对象,需要通过垃圾回收器GC进行判断并回收。

对象存活判断

对象存活检测算法

  1. 引用计数法:一个对象被引用时,将计数器+1,引用失效时,计数器-1。GC时将计数器为0的对象标记为死亡。该方法存在循环引用的问题。

    结局方案:一方使用弱引用,从而避免循环增加计数;检查循环引用之间的对象有没有外部引用

  2. 可达性分析算法:从根节点GC Roots(选定一些对象)出发,判断能否到达某个对象,如果无法到达,则标记为死亡。

缓刑阶段(Java 9 Deprecated / Java 21 Deprecation for Removal)

Object.finalize() 用于对象被垃圾回收器回收时执行一次自我清理的操作,例如打开了一个文件,然后在对象被回收时通过 finalize()回收这个文件。这种机制存在一些缺陷:

  1. 打破了 GC 的回收逻辑,需要两次 GC 才能回收该对象,并且在 finalize 阶段,将其他对象指向当前对象会复活该对象。
  2. Finalize 调用是随机的,无法预测和管理,例如一直创建对象并绑定到一个文件,但是对象没有回收,则 finalize() 不执行,导致内存耗尽。

其替代方式为:try-with-resources / java.lang.ref.Cleaner。

实现了 finalize 的对象会在 GC 中经历两次 GC 周期进行删除。在GC 的第一次标记中会判断对象是否实现finalize方法而决定直接回收还是放入到F-Queue中,然后通过Finalizer Thread 调用这些对象的finalize() 方法,如果这些对象产生了新的引用(复活),则移出队列,否则真正的回收。二次标记取决于对象是否重写了finalize() 方法。单线程并且低优先级的的 Finalizer 守护线程并不可靠,线程阻塞会导致对象积压,引发 OOM 甚至程序崩溃。

引用类型

Jdk1.2之后,Java判断对象存活的粒度从是否存在转变为了引用强度。可达性分析算法是判断两个对象之间的引用从而判断对象是否存活进而清除,而多种引用类型的引入弱化了部分引用的强度,提升了GC的回收率。

  1. 强引用:表示被引用的对象依然存活,即将触发OOM也不会强制回收。
  2. 软引用:根据可计算的保质期或者在Full GC(即将OOM) 时回收软引用对象。具体来说 GC 会采用LRU 策略并结合剩余堆内存空间计算出“保质期”, 而每个对象也会记录最近的被使用时间,在GC时会检测软引用对象是否超过保质期并回收。
  3. 弱引用:只要GC开始工作,都会被回收
  4. 虚引用:并非真正的引用,只是该对象被回收时会发送一条通知。

其中 软、弱、虚引用的对象被GC回收时,可以选择加入ReferenceQueue 中(虚引用必须加入),以便用户程序可以知晓某些资源需要被回收。

其执行流程为:

flowchart TDStart[新对象申请内存] --> Check1{内存够吗?}Check1 -- 够 --> Success[分配成功]Check1 -- 不够 --> Step1%% 第一道防线:常规 GCsubgraph Stage1 ["防线 1: 常规 GC"]Step1["触发 Minor/Mixed/Concurrent GC"]Action1["1. 回收 弱引用 WeakReference<br/>2. 回收 **过期** 的软引用"]Step1 --> Action1endAction1 --> Check2{够了吗?}Check2 -- 够了 --> SuccessCheck2 -- 不够 --> Step2%% 第二道防线:OOM 前的抢救subgraph Stage2 ["防线 2: 暴力抢救 (濒临 OOM)"]Step2["触发 Full GC (G1) 或 同步 GC (ZGC)"]Action2[**无条件清空 所有 软引用**]Step2 --> Action2endAction2 --> Check3{还是不够?}%% 结局Check3 -- 腾出空间了 --> SuccessCheck3 -- 真的没了 --> OOM((抛出 OOM))%% 样式调整style OOM fill:#ff0000,color:#fff,stroke:#333,stroke-width:2pxstyle Action2 fill:#ffcc00,stroke:#333,stroke-width:2px

GC算法

基础方法论

  1. 标记-清除

    标记死亡对象后直接原地删除,优点速度快,缺点是容易产生碎片,导致大对象内存难以分配,被迫触发GC。

  2. 标记-复制

    标记死亡对象后,将存活对象放置到另一块中,然后直接清空原始区域,优点没有内存碎片,缺点是浪费空间。

  3. 标记-整理

    标记死亡对象后,将存活对象防止到内存区域的一侧,然后清理掉另外一侧,优点是内存空间仍完整可用,并且没有内存碎片,缺点是较为耗时。

分代收集

  • 核心假设

    1. 绝大多数对象都是“朝生夕死”的。
    2. 熬过越多次 GC 的对象越难消亡。
  • 常规做法

    • 新生代 (Young Gen):对象存活率低,选用 标记-复制算法
    • 老年代 (Old Gen):对象存活率高、没有额外空间担保,一般选用 标记-清除 或 标记-整理
    • 新生代的对象存活几个周期后,会被移入老年代,大对象可以直接分配到老年代,避免在新生代中频繁的移动。
  • Card Table

    大部分的GC都基于上面的核心假设,采用分代的内存管理以及GC方式。其中Major/Young GC会对年轻代对象进行扫描,以找到其中需要回收的垃圾对象,但是有一部分存活对象只有老年代的引用(跨代引用)。为了避免在 Minor GC 时全量扫描老年代来查找这些引用,可以使用Card Table 记录记录老年代引用了年轻代对象。

    JVM 按照512B的格式将整个堆内存分块为一个个的 Card,并用Card Table 表示。如果区域的老年代引用了年轻代,则通过写屏障技术,更新其CardTable中所在位置的元素。

  • Remembered Set

    记忆集是一个更加抽象的概念,表示非收集区域指向收集区域的指针集合,在G1收集器中采用了RSet 在年轻代Region中记录指向自身的老年代Region地址,这样做的好处是回收某个Region时不需要扫描全部内存区域,缺点是信息需要存储的更多,浪费了可用内存。

并发收集相关算法

三色标记算法

三色标记法通过白色(未访问)、灰色(已访问,但是其引用目标未完全访问),黑色(完全访问)三种颜色标记对象,主要分为三个阶段,三个阶段后如果对象还是白色,则认为可以回收:

  1. 初始标记:STW, 将GC Roots直接引用的对象, 标记为灰色(未访问其子节点)
  2. 并发标记:解除STW, 应用线程与GC线程并发执行,将灰色集合中的一个对象标记为黑色,并将其引用的所有白色对象标记为灰色,重复此步骤直到灰色集合清空。
  3. 重新标记: STW(可选)不断重复第二步,直到队列为空。

对象消失问题

由于并发阶段用户线程是可以正常执行的,所以这个过程中,用户线程对于对象图的修改操作会导致对象消失的问题,当以下两个事件同时发生就会产生对象消失问题。

  1. 插入条件:一个黑色节点指向了白色节点;
  2. 删除条件:并且所有灰色节点删除了对于该白色节点的引用

也就是说在并发标记阶段由于用户的修改导致了一个存活节点被判定为可以回收,不同的GC 采用了不同的策略:

  • CMS(增量更新),破坏条件 1黑色节点产生的新引用后会被重新标记为灰色必须设置STW 最终标记阶段进行重新扫描,导致性能低下。实现方式是在赋值操作前添加了写屏障的代码以记录该灰色节点。
  • G1 (SATB原始快照),破坏条件 2,通过写屏障保留被删除的引用,并加入到集合中,等待 STW 的最终标记阶段扫描少量的SATB 队列。对于新分配的对象则直接标记为黑色。
  • ZGC(染色指针&读屏障),破坏条件 1, 当一个白色节点赋值给一个黑色节点之前,读屏障的会立即检查白色节点指针,并将其染成当前周期的标记色。
  • Generational Shenandoah(SATB + Load Barrier):与G1 一致,采用SATB ,只回收GC开始前的对象。

垃圾收集器

选择合适的垃圾收集器有助于提升程序性能,相反不合适的垃圾收集器可能会降低程序性能,一般由以下三个指标来衡量GC的优化效果。

  • 吞吐量:表明程序执行的有效时间,越高越好

$$
\text{吞吐量} = \frac{\text{运行用户代码时间}}{\text{运行用户代码时间} + \text{GC 垃圾回收时间}}
$$

  • 暂停时间:GC时程序暂停(STW)的最长时间,越小越好
  • 内存占用:GC所需要的额外的内存开销,以及所适合的堆内存大小,越小越好

对于 G1 来说,其追求的是可控的暂停时间,所以三个指标比较均衡,而 ZGC 与 Shenandoah 为了追求极低的暂停时间,需要消耗更多的 CPU 与内存,导致吞吐量与内存占用略差于 G1。

CMS 简述

CMS(Concurrent Mark Sweep) 用于 Major GC,一般与ParNew 的 Young GC 组合使用。主要采用三色标记算法,在初始标记时较短的STW,并发标记和清除性能尚可,最终标记可能稍长时间的 STW。其存在 CPU 占用高、无法处理浮动垃圾等缺点,但是其采用了标记-清除算法导致了过多的内存碎片产生,以及预留内存(浮动垃圾)不足,导致在 GC 运行时内存又不足以分配,而产生的严重的并发失败问题:将会强行启动 Serial Old (JDK8 标记-整理),使用单线程对老年代进行标记-整理,可能会 STW 几十秒到几分钟。

G1 简述

G1 (Garbage First) 是一个分代分区(Region之间标记-复制,整体看作标记-整理) 的垃圾收集器,其特点是支持配置最大停顿时间,一次GC时会尽力满足该时间内完成垃圾回收。G1 支持 Young GC 模式以及 Mixed GC 模式,会根据GC停顿时间进行年轻代区域大小的划分,确保当年轻代满了之后可以在一次Young GC 内回收完毕。

当堆内存占用超过 45% 时,G1 执行一次并发标记以计算 Region 价值,随后切换到 Mixed GC 模式,按照 Region 价值顺序执行多次 Mixed GC (每一次都STW,但是尽量满足最大暂停时间)以降低堆内存占用到45% 以下。

当内存分配速度超过GC 速度时,也会触发 Full GC,但是采用了多线程的方式,性能优于 CMS,且大对象会直接分配到Humongous Region中(逻辑参考老年代,GC 时会直接释放空间),避免拷贝开销。

从指标来看,G1 不追求极低的暂停时间,而是通过可控的暂停时间下,尽量保证吞吐量。

ZGC 简述

ZGC (Z Garbage Collector) 是一款基于分页(ZPage)和染色指针技术的低延迟垃圾收集器。

在内存布局方面,采用了动态大小的ZPage 作为管理单位并对齐到 OS Page,从而提升 TLB 访问效率。实现了全流程的并发(标记、转移、重映射),核心依赖与染色指针存储对象状态,配合读屏障来解决并发冲突:

  • 并发标记阶段,利用读屏障实现强三色不变性,应用线程读取对象引用,则将其标记为当前标记色
  • 并发转移阶段,将对象复制到新页,并利用 Forward Table 记录对象的新地址。如果应用程序访问存活对象,则会被读屏障拦截,立即复制该对象并修正旧地址的引用,称为自愈能力。
  • 并发重映射阶段,修正旧地址的引用,ZGC 会将这一步合并到下一次 GC 的并发标记阶段。

从指标来看,ZGC 可以达到极低的暂停时间,但是会带来GC并发线程的CPU以及额外空间(Forward Table)的内存占用,非常适合大内存且对响应时间敏感的场景。

Generational Shenandoah 简述

  1. 目标与ZGC 类似,设计为超低延迟(10ms 级别)的并发垃圾收集器,支持多种回收算法:
    1. 自适应回收
    2. 设定回收堆大小的阈值。
    3. 紧凑型回收,距离上一次回收后内存分配的阈值来确定立即进行下一次回收
  2. 支持在较低版本的JDK8 / JDK 11使用超低延迟的方案。
  3. 采用了CardTable 以支持分代,并使用SATB方式,只回收GC开始前存活的对象
  4. Forwarding Pointer :对象头上会添加“自我指针”,保存着GC后的对象所在位置,当访问到旧对象的时候,会被读屏障拦截,重新定位到新的地址。

三者的STW差异

G1 的Young GC 是STW的,其停顿预测模型会根据停顿时间通过Parallel 方式快速回收,其中较为耗时的部分是将存活对象复制到其他的Region ,如果将停顿时间设置过短,就会导致分配的年轻代区域空间过小,最终导致OOM。

而 ZGC 与 Shenandoah 采用了并发标记、转移的方式,并结合染色指针+写屏障/自我指针+读屏障的方式,即使在并发过程中应用线程访问了对象,也可以被屏障拦截立即纠错应用指针,所以可以降低STW时间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/990374.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“游戏无法启动”、“DLL文件丢失”或“缺少组件”怎么办

完全免费、无任何付费项目,「运行库检测工具」专注于解决游戏运行库问题,确保玩家无需额外开销即可畅玩游戏。「运行库检测工具」由XDGAME倾力打造的单机游戏必备助手。它能一键解决游戏运行库的各类问题,让你轻松回…

家用轿车轮胎推荐:十大家轿胎深度榜单

家用轿车轮胎推荐:十大家轿胎深度榜单在消费升级与家用车使用场景日趋多元化的当下,家用轿车轮胎推荐正面临前所未有的复杂挑战。越来越多的车主发现,传统“耐磨就行”“静音就好”的单一诉求,已无法覆盖日常代步、…

Less-8 GET-Blind-Boolean Based-Single Quotes - 详解

Less-8 GET-Blind-Boolean Based-Single Quotes - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas&q…

舒适的轮胎推荐:TOP10舒适胎专业测评

舒适的轮胎推荐:TOP10舒适胎专业测评在高端出行日益成为一种生活态度的当下,越来越多的车主不再满足于轮胎只扮演“默默支撑”的角色,而是期待它在每一次转动间,赋予座舱宁静、柔韧与安稳,把驾驶还原为一种身心舒…

2025年节油的轮胎推荐:权威省油胎最新榜单

2025年节油的轮胎推荐:权威省油胎最新榜单在全球汽车产业加速向电动化转型的背景下,用户对轮胎的期待已从传统的“耐用”“安全”延伸至“能效优化”与“全场景适配”。2025年节油的轮胎推荐正成为新能源车主与注重能…

2025年丰田凯美瑞更换轮胎推荐:权威轮胎推荐必读攻略

2025年丰田凯美瑞更换轮胎推荐:权威轮胎推荐必读攻略在当前中高端家用轿车市场中,2025年丰田凯美瑞依旧凭借均衡的驾控质感、宽敞的空间表现与稳定的品质口碑,稳居中型轿车的主流阵营。然而,伴随轮胎服役周期的到来…

2025年本田雅阁更换轮胎推荐:专业轮胎选择深度解析

2025年本田雅阁更换轮胎推荐:专业轮胎选择深度解析在当前中高端轿车市场中,2025年本田雅阁依旧凭借均衡的操控质感、宽敞的乘坐空间与高效的燃油经济性,稳居家庭与商务用户的首选阵营。然而,伴随轮胎更换周期的到来…

奔跑

我看到了远处有一块的金条,愁绪便消散了。 我兴奋地跑了过去,可那块金条似乎越来越远了。 我便加快了速度。 几万年后,我终于跑到了那金条的面前。 仔细看了一眼才发现那哪是一块金条啊,分明是一片金黄的落叶。 我…

论文写作辅助必备!7款AI工具让你轻松搞定论文,查重无忧

2025年冬,作者写论文愁眉不展,经邻桌同学提点开启AI辅助写作探索。作者试用7款AI论文工具后,分享使用实战经验。包括瑞达写作、PaperFine、PaperTan等,各工具有不同特点,如瑞达写作能30分钟生成初稿、覆盖多类型论…

运动补偿中的距离对准技术:原理、方法与应用

一、概述:运动补偿与距离对准的定义 1. 运动补偿的背景 在激光雷达(LiDAR)、合成孔径雷达(SAR)、超声成像等主动遥感系统中,平台运动(如无人机、卫星、车辆、机器人)会导致传感器与目标间的相对位置动态变化,…

记一次Sqlserver数据库存储过程调用导致的连接池耗尽事件

背景: 有两台数据库服务器IP分别为A和B。 (1)A服务器上有一个存储过程名称Proc_A,B服务器上有一个存储过程名称Proc_B, A服务器上有B服务器上远程数据库链接,B服务器上也有A服务器上远程数据库链接。 (2)在A服务…

2025/12/6下午计划

2025/12/6下午计划现在时间是16:19,上午11点起来后吃饭刷短视频打排位,脑子也没记下什么事情。今天还可以继续学到19点。 1.学习编译原理。为期末考试做准备。优先搞懂作业七和作业九。再看看ppt和课本。实验方面搜…

2025年下半年上海ISO27001认证机构综合评估与选择指南

摘要 随着信息安全威胁日益复杂,ISO27001认证成为企业信息安全管理的重要标准。2025年下半年,上海地区认证服务市场呈现专业化、细分化的趋势,本文基于行业调研数据,为需要认证服务的企业提供客观参考。文末附联系…

Spring Boot:核心概念、核心特性与实战应用全解析

Spring Boot 是 Pivotal(后并入 VMware)基于 Spring 框架推出的快速开发脚手架,核心定位是 “约定优于配置”—— 通过自动配置、 starters 依赖封装、嵌入式服务器等特性,简化 Spring 应用的搭建、配置与部署流程…

2025年下半年上海ISO27001认证平台口碑排行榜

摘要 随着信息安全意识的提升,ISO27001认证在2025年下半年成为上海企业关注的焦点。本文基于行业数据、用户反馈和专家评测,为您呈现上海地区ISO27001认证服务商的综合排名,旨在帮助企业选择可靠合作伙伴。排名综合…

Spring Boot和Spring有什么区别?

Spring 和 Spring Boot 并非 “替代关系”,而是 **“基础框架” 与 “快速开发脚手架”** 的互补关系 ——Spring 是 Java 生态的核心企业级框架,定义了依赖注入(DI)、面向切面编程(AOP)等核心规范;Spring Boot…

2025年下半年上海ISO三体系认证服务专业机构深度评测与选择指南

摘要 随着2025年企业标准化管理需求的不断提升,上海ISO三体系认证服务行业迎来新一轮发展机遇。本文基于市场调研和用户反馈,对上海地区ISO认证服务机构进行客观评估,为有认证需求的企业提供参考依据。文末附有专业…

2025年下半年上海ISO三体系认证服务商全面评测与选择指南

摘要 随着2025年企业国际化进程加速,上海ISO三体系认证行业迎来新一轮发展高峰,认证需求同比增长15%以上(数据来源:中国认证认可协会2025年报告)。本文基于市场调研和用户反馈,深度解析top5认证服务商,并提供客…

2025年五大直流电源供应商推荐,有名的直流电源企业与全解析

在新能源革命、半导体精密检测与工业智能制造蓬勃发展的当下,高精度、高可靠性的直流电源已成为各行业研发与生产的核心基石。面对市场上种类繁多的直流电源产品,如何精准选择契合自身需求的供应商?以下依据技术实力…