Java 的 G1 垃圾回收流程是怎样的?

Sherwin.Wei Lv8

Java 的 G1 垃圾回收流程是怎样的?

回答重点

G1 从大局上看分为两大阶段,分别是并发标记对象拷贝

并发标记

并发标记是基于 SATB 的,可以分为四大阶段:

**1)初始标记(initial marking)**,这个阶段是 STW 的,扫描根集合,标记根直接可达的对象即可。在G1中标记对象是利用外部的bitmap来记录,而不是对象头。

2、并发阶段(concurrent marking),这个阶段和应用线程并发,从上一步标记的根直接可达对象开始进行 tracing,递归扫描所有可达对象。 SATB 也会在这个阶段记录着变更的引用。

**3)最终标记(final marking)**,这个阶段是 STW 的,处理 SATB 中的引用。

4)清理阶段(clenaup),这个阶段是 STW 的,根据标记的 bitmap 统计每个 region 存活对象的多少,如果有完全没存活的 region 则整体回收。

对象拷贝阶段(evacuation)

这个阶段是 STW 的。

根据标记结果选择合适的 reigon 组成收集集合(collection set 即 CSet),然后将 CSet 存活对象拷贝到新 region 中。

G1 的瓶颈在于对象拷贝阶段,需要花较多的瓶颈来转移对象。

扩展知识

G1 垃圾回收器调优参数

1)最大停顿时间

  • 使用参数 -XX:MaxGCPauseMillis=<N> 设置希望的最大停顿时间(毫秒)。G1 会尽量在这个时间范围内完成垃圾回收,以满足响应时间要求。

2)堆区域大小

  • 通过 -XX:G1HeapRegionSize=<size> 设置每个区域的大小。合适的区域大小可以影响回收效率,通常选择的大小为 1MB、2MB 或 4MB。

3)保留比例

  • 使用 -XX:G1ReservePercent=<percentage> 设置 G1 的保留比例,指的是保留未分配的堆内存的百分比,以避免频繁的 Full GC。

4)年轻代占比

  • 通过 -XX:G1NewSizePercent=<percentage>-XX:G1MaxNewSizePercent=<percentage> 设置年轻代的最小和最大占比,控制新生代的大小,影响年轻代的回收频率和效率。

5)并发线程数

  • 使用 -XX:G1ConcMarkThreads=<N> 设置并发标记阶段使用的线程数量。增加线程数可以提高标记速度,适合多核处理器。

6)启用混合回收

  • 使用参数 -XX:G1MixedGCLiveThresholdPercent=<percentage> 设置活跃对象在区域回收中的阈值,以决定哪些区域进行混合回收。
Comments