9 G1 回收器

定义:Garbage First

  • 04年论文发布

  • 09年JDK 6u14体验

  • 12年JDK 7u4官方支持

  • 17年JDK9默认

适用场景

  • 同时注重吞吐量和低延迟,默认的暂停目标是200ms

  • 超大堆内存,会将堆划分为多个大小相等的Region,每个区域都可作为伊甸园,幸存区,老年代

     

  •  整体是标记+整理算法,两个区域Region之间是复制算法

相关JVM参数

-XX:+UseG1GC JDK8启用G1GC JDK9就是默认的,不用显示启用

-XX:G1HeapRegionSize=size 设置区域大小

-XX:MaxGCPauseMillis=time

9.1 G1 垃圾回收阶段

1)Young Collection :新生代的收集阶段

如果伊甸园的内存满了,那G1就开始进行垃圾回收,最后把幸存的对象复制到幸存区

再工作一段时间,幸存区的对象有一部分会晋升到老年代,其它年龄小的复制到另外一个幸存区去

2)Young Collection+Concurrent Mark 阶段

  • 初始标记就是说我要找到那些根对象。并发标记呢 是从根对象出发,顺着他的链路去标记 其它对象。

  • 老年代占用空间比例达到阈值时,会触发并发标记(不会stw)。阈值可以通过JVM的一个参数来设定:-XX:InitiatingHeapOccupancyPercent=percent(默认45%)

3)Miaed Collection:混合收集阶段

会对E,S,O进行全面的垃圾回收

为了达到一个设定的时间,G1会去老年代里面在限定时间内找出回收价值最高的老年代。来进行垃圾回收,这样复制区域小了,就能达到完美理想时间。

为什么叫Garbage First呢?含义就是优先回收垃圾最多的区域

 最终标记就是找出并发标记的漏网之鱼。

9.2 垃圾回收器的对比

前两个触发full GC的条件都是老年代内存不足就触发。但是后两个和他们略有差异。

G1里面老年代内存不足,并且你产生新垃圾的速度大于我收垃圾的速度,并发收集失败,退化为串行收集。那我就全面回收full gc。CMS也一样。

9.3 Young Collection跨代调用

新生代收集的时候会去找根对象,那根对象有些是在老年代里面,如果我把老年代全部遍历一遍去查找,那效率是很低的。因此采用一种卡表计数,把老年代的内存再进行细分。如果老年代的一个对象引用新生代,那就标记为脏卡。那我以后只需要关注我标记的对象,减少搜索范围,提高效率。新生代这边有一个Rembered Set 去记录都有哪些脏卡。将来对新生代垃圾回收的时候,通过这个set去老年代里面找。

那么标记脏卡之后,会把脏卡放到一个队列当中,将来方便维护。

9.4 Remark

黑色将来保存的,灰色正在处理 ,白色未处理。

垃圾回收时根据黑白来决定该存活还是要当成垃圾。

我们来看这样一种情况,本来c是和b有强引用关系,但是并发过程中强引用断开了,所以c被标记为白色。要被回收,但是这时候又有并发线程A强引用C。那不就糟糕了吗,我c已经被标记为白色了,必须要被干掉。这样对A的伤害是很大的,所以有了remark。

 当引用发生改变的时候,我加入一个写屏障,然后把c放到一个队列当中,并且变为灰色,当重新标记来了之后,就标记为黑色,就不会被回收掉了。

9.5 G1的优化过程

 

 

 

原文地址:https://www.cnblogs.com/YXBLOGXYY/p/15530489.html