java虚拟机面试干货【拾】_G1 GC的回收机制

上篇文章:java虚拟机面试干货【玖】_G1 GC的空间划分


简单来说,G1 GC的收集分为4个阶段:年轻代GC,并发标记周期,混合回收和full GC。


年轻代GC


G1 GC的年轻代回收基本沿袭了之前的设计,通过复制算法和一个Eden区、两个Survivor区实现。但区别在于,大对象的分配是可以直接到大对象区间的(详见上文)。此外,在每一次年轻代回收暂停期间,G1 GC会计算当前年轻代大小需要扩展或者压缩的总量,例如增加或者删除空闲区间、统计Rset大小、当前最大可用年轻代、当前最小可用年轻代、设置停顿目标等。我们可以认为这个过程在回收停顿结束后是一个重新调整年轻代的过程。可以通过-XX:+PrintGCDetails选项的运行来查看具体数据。


并发标记


G1 GC设定了一个阈值,默认值是堆内存的45%。这个阈值可以通过选项IHOP设定,IHOP即-XX:InitiatingHeapOccupanyPercent。当超过阈值时,GC会自动进入并行标记循环。并行标记循环的最终目标是在整个Java堆达到满载之前完成标记动作,同时为了确保Java应用线程可以并行运行,并行标记循环的内部标记任务被划分成了很多块任务,这样可以做到并行执行。


并行标记循环的过程分为五个阶段:


1.初始标记阶段

把java堆中所有能被根可达的对象标记出来,在此期间应用线程暂停。


2.根区间扫描阶段

并发扫描和跟踪survivor区所有对象引用。


3.并行标记阶段

多个线程协同表示存活对象。并发并行执行。


4.重新标记阶段

最终完成所有标记工作,短暂stop-the-world。


5.清除阶段

将没有任何存活对象的分区回收,梳理RSet,将没有引用的分区加入可用队列。



混合回收


混合回收和年轻代回收暂停的工作方式类似,也是通过拷贝方式完成针对存活对象的压缩操作。唯一的区别是在混合回收阶段,回收集合也会和一些被认定为是可以做垃圾回收的老年代一起合作,即同时对年轻代和老年代区间进行回收。通过配置一些参数,可以为一次混合回收循环设定多次混合回收暂停。一次混合回收循环只有在标记或者超过IHOP阔值时才会触发启动,且必须发生在一次并行标记循环之后。

可配置参数:


-XX:-G1MixedGCCountTarget

DK8u45默认值为8, 意味着混合GC数目目标为8个,即标记循环完成之后开始的混合回收数目从物理上被限制在了8个。每一次混合回收暂停的最小老年代区间数目的计算公式为:

每一次混合回收暂停的最小老年代区间数目=混合收集循环确认的候选老年代区间总数/G1MixedGCCountTarget。



-XX:G1HeapWastePercent

JDK8U45默认值为整个堆空间的5%, 这个选项对于控制一次混合回收循环回收的老年代区间数量有很大的影响作用。对于每一次混合回收暂停, G1 GC基于死亡对象空间确认所有可以回收的堆内存,即事先已经统计好了每个区间还有多少存活对象,通过拷贝的方式移出区间,再把这些区间加入空闲区间。当G1 GC达到堆内存空闲阈值百分比限制时,G1 GC停止初始化混合回收暂停。





你可能感兴趣的:(java虚拟机)