垃圾回收过程

如何回收:

1、标记。扫描所有堆中的对象,并标记需要回收的对象所在的内存;

2、清除上一步标记的需要回收的对象区域,此时会产生碎片问题,标记清除后会产生大量不连续的内存碎片;

     2.1、因此出现压缩清除的方法。先清除需要回收的对象,然后再对内存进行压缩,将内存分成可用和不可用两大部分。


上述回收效率低,回收时间长,有人分析出来,一个程序中大部分的对象都是短命的,因此,为了提高回收效率,JVM将堆进行分代,一般分为新生代、老年代、永久代



分代垃圾收集过程详述

1、所有new出来的对象都会最先分配到新生代区域中,两个survivor(S0和S1)区域初始化是为空的


2、当伊甸园区域满了之后,就会引发一次minor garbage collection(小型垃圾回收);


3、当在minor garbage collection(小型垃圾回收),存活下来的对象就会被移到S0区域;


4、当伊甸园区域再次填满时,又会发生下一次垃圾回收,存活下来的对象会被移到survivor区域,而未存活的对象则被直接删除,但是,不同的是,在这次垃圾回收中,存活对象和之前在S0区域中的对象都会移到S1区域中。一旦所有对象都被移到S1区域中,那么S0中的对象就会被清除;


5、下一次的垃圾回收的时候,又会重复上次的步骤,清除需要回收的对象,并且切换一次survivor区域,所有存活的对象都被移到S0,伊甸园区域和S1区域被清除;


6、重复以上步骤,并记录对象的年龄(记录垃圾回收的次数),当有对象的年龄达到一定的阈值时,就将新生代中的对象移到到老年代。比如下图,这个阈值为8;


7、接下来垃圾回收就会重复以上步骤,不断的进行对象的清除和年代的移动;


8、观察上述步骤发现,大部分的垃圾回收过程都是在新生代进行的,直到老年代的内存不够用了才会发起一次minor GC ,会进行标记和整理压缩。


Go 1.8 版本的垃圾回收(GC)机制在性能和效率方面进行了显著优化,主要引入了 **混合写屏障(Hybrid Write Barrier)** 技术,并延续了之前版本中使用的 **三色标记法(Tricolor Marking)**,实现了并发、非移动、非分代的垃圾回收机制。 ### 垃圾回收的基本流程 Go 的垃圾回收流程主要分为以下几个阶段: #### 1. 启动 GC(gcStart) GC 的入口函数是 `gcStart()`,它根据当前的 GC 模式决定如何处理垃圾回收。在 Go 1.8 中,GC 支持后台运行(并行)模式(`gcBackgroundMode`)和主动触发模式[^3]。 - 如果是后台运行模式,GC 会从 `_GCoff` 状态切换到 `_GCmark` 状态,表示进入标记阶段。 - 如果是主动触发模式,则会进入 `_GCmarktermination` 状态,表示标记阶段即将结束。 #### 2. 标记阶段(Marking Phase) 标记阶段是 GC 的核心部分,Go 1.8 中采用了 **三色标记法**,将对象分为三种状态: - 白色:未被访问的对象(待回收)。 - 灰色:自身被访问,但子对象未被完全访问。 - 黑色:自身和子对象都被访问。 标记过程从 **根对象**(Root Objects)出发,包括全局变量和每个 goroutine 的执行栈上的变量,逐步标记所有可达的对象为“存活”[^4]。 - 在 Go 1.5 及之前版本中,三色标记法虽然支持并发执行,但需要 STW(Stop The World)来确保根对象的准确性。 - 在 Go 1.8 中,引入了 **混合写屏障(Hybrid Write Barrier)**,可以避免在标记阶段结束时进行长时间的 STW。混合写屏障结合了插入写屏障(Insertion Write Barrier)和删除写屏障(Deletion Write Barrier),确保并发标记过程中对象图的正确性[^1]。 #### 3. 标记终止阶段(Mark Termination) 该阶段主要完成标记工作的收尾工作,包括: - 处理所有灰色对象,确保所有可达对象都被标记为黑色。 - 清理标记过程中可能遗漏的对象。 - 进行最终的 STW,以确保所有并发标记操作已完成。 这一阶段仍然需要短暂的 STW,但相比之前的版本,时间大大缩短。 #### 4. 清除阶段(Sweeping Phase) 清除阶段负责回收所有未被标记的对象(白色对象),并将这些内存空间归还给内存分配器,供后续分配使用。 - 该阶段与用户程序并发执行,进一步减少对程序性能的影响。 - 清除操作会移动对象,因此会产生内存整理(Compact)的开销。 ### 垃圾回收中的关键优化 #### 混合写屏障(Hybrid Write Barrier) 混合写屏障是 Go 1.8 中引入的关键优化之一,它解决了并发标记过程中对象图一致性的问题。具体来说: - 插入写屏障确保新引用的对象会被错误回收。 - 删除写屏障确保被删除引用的对象会提前被回收。 - 两者的结合使得在并发标记过程中,GC 可以正确追踪对象的存活状态,从而减少 STW 的时间。 #### 三色标记法的并发执行 Go 的三色标记法允许 GC 与其他用户 goroutine 并发运行,减少对程序性能的影响。标记操作可以渐进式执行,而需要一次性扫描整个内存空间,从而显著减少 STW 的时间。 ### 示例代码:Go 1.8 中的 GC 启动逻辑 ```go func gcStart(mode gcMode, forceTrigger bool) { // 根据模式处理 GC 启动 if mode == gcBackgroundMode { // 后台运行模式,进入标记阶段 setGCState(_GCmark) } else { // 主动触发模式,进入标记终止阶段 setGCState(_GCmarktermination) } // 其他初始化逻辑... } ``` ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值