定义:Garbage First
-
04年论文发布
-
09年JDK 6u14体验
-
12年JDK 7u4官方支持
-
17年JDK9默认
适用场景
- 超大堆内存,会将堆划分为多个大小相等的Region,每个区域都可作为伊甸园,幸存区,老年代
- 整体是标记+整理算法,两个区域Region之间是复制算法
-XX:+UseG1GC JDK8启用G1GC JDK9就是默认的,不用显示启用
-XX:G1HeapRegionSize=size 设置区域大小
-XX:MaxGCPauseMillis=time
1)Young Collection :新生代的收集阶段
2)Young Collection+Concurrent Mark 阶段
3)Miaed Collection:混合收集阶段
会对E,S,O进行全面的垃圾回收
为什么叫Garbage First呢?含义就是优先回收垃圾最多的区域
最终标记就是找出并发标记的漏网之鱼。
9.2 垃圾回收器的对比
前两个触发full GC的条件都是老年代内存不足就触发。但是后两个和他们略有差异。
G1里面老年代内存不足,并且你产生新垃圾的速度大于我收垃圾的速度,并发收集失败,退化为串行收集。那我就全面回收full gc。CMS也一样。
9.3 Young Collection跨代调用
新生代收集的时候会去找根对象,那根对象有些是在老年代里面,如果我把老年代全部遍历一遍去查找,那效率是很低的。因此采用一种卡表计数,把老年代的内存再进行细分。如果老年代的一个对象引用新生代,那就标记为脏卡。那我以后只需要关注我标记的对象,减少搜索范围,提高效率。新生代这边有一个Rembered Set 去记录都有哪些脏卡。将来对新生代垃圾回收的时候,通过这个set去老年代里面找。
那么标记脏卡之后,会把脏卡放到一个队列当中,将来方便维护。
黑色将来保存的,灰色正在处理 ,白色未处理。
垃圾回收时根据黑白来决定该存活还是要当成垃圾。
我们来看这样一种情况,本来c是和b有强引用关系,但是并发过程中强引用断开了,所以c被标记为白色。要被回收,但是这时候又有并发线程A强引用C。那不就糟糕了吗,我c已经被标记为白色了,必须要被干掉。这样对A的伤害是很大的,所以有了remark。
当引用发生改变的时候,我加入一个写屏障,然后把c放到一个队列当中,并且变为灰色,当重新标记来了之后,就标记为黑色,就不会被回收掉了。