Java 的 G1 垃圾回收流程是怎样的?
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