G1垃圾回收

2020-05-12  本文已影响0人  Yves_Chen
G1垃圾回收.png

G1

调优场景

Evacuation Failure

"evacuation failure", "to-space exhausted", "to-space overflow", "promotion failure"之类的字眼。这些术语的概念在G1 GC是相似的

巨型对象和巨型对象分配

对于 G1 GC,任何超过区域一半大小的对象都被视为“巨型对象”。此类对象直接被分配到老年代中的“巨型区域”。这些巨型区域是一个连续的区域集。StartsHumongous 标记该连续集的开始,ContinuesHumongous 标记它的延续。

在分配任何巨型区域之前,会检查标记阈值,如有必要,还会启动一个并发周期。

在清理阶段或完整的垃圾回收周期内,标记周期结束时会清理死亡的巨型对象。

为了减少复制开销,巨型对象未包括在疏散暂停中。完整的垃圾回收周期会对巨型对象进行压缩。

由于每个 StartsHumongous 和 ContinuesHumongous 区域集只包含一个巨型对象,所以没有使用巨型对象的终点与上个区域的终点之间的空间(即巨型对象所跨的空间)。如果对象只是略大于堆区域大小的倍数,则此类未使用的空间可能会导致堆碎片化。

如果巨型分配导致连续的并发周期,并且此类分配导致老年代碎片化,请增加 -XX:G1HeapRegionSize,这样一来,之前的巨型对象就不再是巨型对象了,而是采用常规的分配路径。

当未找到能放下巨型对象的连续分区时,G1会首先尝试扩展堆空间,扩展失败时,启动串行gull gc。

引用处理

-XX:PrintReferenceGC在GC日志中输出各种引用详细GC数据。

通常,在G1年轻代或者混合收集中,当PrintGCDetails输出中的Ref Proc时间超过GC暂停时间总数的10%时,需要进行调优:

1.-XX:+ParalleRefProcEnabled激活多线程引用处理,负面影响是会抢占用户线程时间片。

2.第一点作用不明显时,观察GC日志,找到导致Ref Proc处理时间过长的引用类型,优化应用程序减少对该类型引用的使用。

软引用特别说明:

由于软引用对象只会在OOM前回收,所以软引用对象可能会长期占用内存而频繁触发老年代收集周期,使用-XX:SoftRefLRUPolicyMSPerMB可以控制软引用对象回收时机,

回收周期

年轻代GC

对象从eden区分配失败时触发,copy eden + from survivor -> to survivor,超过晋升阈值的对象copy到老年代。

混合GC

触发时机:

当老年代分区占用总堆比例超过阈值(默认45%)时,触发混合GC。

初始标记:和下一次年轻代GC一起,STW并行标记,收集所有的GC Roots。

并发标记:多线程并发协同标示存活对象图。

重新标记:STW并行重新标记上个阶段产生的新垃圾。

并行回收:垃圾清理。

增大该值将会占用应用线程处理时间,降低吞吐量,因为并发GC线程和应用线程同时工作。

- -XX:InitiatingHeapOccupancyPercent IHOP 45%

  老年代占用比例超过该值时触发并发标记周期。

https://www.jianshu.com/p/9e70097807ba

高效率的分区:

1.存活对象少。

2.对象被别的分区对象引用数量少。这里数量多会导致RSet中PRT粒度粗化,增大RSet扫描开销。

交换位图、指针?并发标记周期也交换?

  每次混合收集老年代CSet的最小数量 = 混合收集周期将回收的候选老年代分区总数/G1MixedGCCountTarge

  

  

- -XX:G1HeapWastePercent 10%

  混合收集周期中发现垃圾占总堆比例低于该值时,停止混合收集周期

- -XX:G1OldCSetRegionThresholdPercent 10%

  每次混合收集暂停收集分区上限,默认总堆的10%

Full GC

触发时机:对象分配失败时?

使用串行垃圾收集器对整个堆全面压缩。

G1的设计目标通过不断调优而不再需要full GC。

公共

1MB~32MB,G1默认将堆划为为约2048个Region。

copy对象到to-space时产生对象晋升,老年代空间不足时会扩展老年代堆空间,老年代空间已达上限会产生晋升失败,增大预留内存占比可避免晋升失败。

如果逻辑处理器不止八个,则将 n 的值设置为逻辑处理器数的 5/8 左右。这适用于大多数情况,除非是较大的 SPARC 系统,其中 n 的值可以是逻辑处理器数的 5/16 左右。

堆空间调整

JVM通过在Xms和Xmx之间动态调整堆大小及年轻代大小,以满足用户设置的GC暂停时间MaxGCPauseMillis和GCTimeRatio(用户线程时间/GC线程时间)的目标。

RSet

引用关系

PRT 粒度?

关系维护

维护时机:

对象引用关系变化时(包括引用赋值、GC移动对象等),触发写栅栏代码,维护Rset。

若发生一个跨区引用关系变化,G1垃圾收集器会将相应的card加入到“脏卡片队列”。“并发优化线程”会扫描队列中的卡片来更新RSet。当“并发优化线程”来不及处理不过来时,会挂起用户线程,让用户线程也加入到更新Rset。

全局卡片表

在任意收集周期,扫描Rset与PRT时,会将扫描到的引用记录标记到全局卡片表,避免重复扫描。在收集周期的最后将该表清空,显示为Clear CT。

工作窃取机制

收集活动图

活动流程

关键算法

https://www.jianshu.com/p/548c67aa1bc0

RSET

年轻代收集

如何确保新生代对象被老年代引用的时候不被gc?(查询老年代对象来确认对新生代对象的引用避免误回收)

机制:当老年代存活对象多时,每次minor gc查询老年代所有对象影响gc效率(因为gc stop-the-world),所以在老年代有一个write barrier(写屏障)来管理的card table(卡表),card table存放了所有老年代对象对新生代对象的引用。

所以每次minor gc通过查询card table来避免查询整个老年代,以此来提高gc性能。

初始标记

并发标记周期

混合收集周期

GC日志

跑出完成GC日志,标记日志说明。

https://www.jianshu.com/p/ac1ba3479c08

引用

堆外内存回收

https://www.jianshu.com/p/35cf0f348275

Reference&ReferenceQueue

https://www.jianshu.com/p/f0da6c1af815

finalize

https://www.jianshu.com/p/9d2788fffd5f

上一篇下一篇

猜你喜欢

热点阅读