G1垃圾收集器角色划分与重要概念详解
-
G1重要概念
-
分区(Region):G1采用了不同的策略来解决并行、串行和CMS收集器的碎片、暂停时间不可控等问题——G1将整个堆分成大小相同的分区(Region);
-
每一个分区都可能是年轻代,也可能是老年代,但是在同一时刻只能属于某一个代。年轻代、幸存区、老年代这些概念还存在,成为逻辑上的概念,这样方面复用之前分代框架的逻辑;
-
在物理上不需要连续,则带来了额外的好处——有的分区内垃圾对象特别多,有的分区内垃圾对象很少,G1会优先回收垃圾对象特别多的分区,这样可以花费较少的时间来回收这些分区的垃圾,这也就是G1名字的由来,即首先收集垃圾最多的分区;
-
依然是在新生代满了的时候,对整个新生代进行回收(即Eden空间无法容纳下新创建的对象的时候)——整个新生代中的对象,要么被回收、要么晋升,至于新生代也采取分区机制的原因,则是因为这样跟老年代的策略统一,方便调整代的大小。
-
G1还是一种带压缩的收集器,在回收老年代的分区时,是将存活的对象从一个分区拷贝到另外一个分区,这个拷贝的过程实现了局部的压缩;
-
收集集合(CSet):**一组可被回收的分区的集合。**在CSet中存活的数据会在GC过程中被移动到另一个可用分区,CSet中的分区可以来自eden空间,survivor空间或者老年代。
-
已记忆集合(RSet):RSet记录了其他Region中的对象引用本Region中对象的关系,属于points-into结构(谁引用了我的对象)。RSet的价值在于使得垃圾收集器不需要扫描整个堆谁引用了当前分区中的对象,只需要扫描RSet即可。
-
Region1和Region3中的对象都引用了Region2中的对象,因此在Region2的RSet中记录了这两个引用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-n4uSPO5b-1590580862373)(G:\笔记\图片\1580651617876.png)]
-
G1 GC是在points-out的card table之上再加了一层结构来构成points-into RSet:每一个region会记录下到底哪些别的region有指向自己的指针,而这些指针分别在那些card的范围内。
-
这个RSet其实是一个hash table,key是别的region的起始地址,value是一个集合,里面的元素是card table的index。举例来说:如果region A的RSet里有一项的key是region B,value里有index为1234的card,它的意思就是region B的一个card里有引用指向region A。所以对region A来说,该RSet记录的是points-into的关系;而card table仍然记录了points-out的关系。
-
-
Snapshot-At-The-Begining(SATB):SATB是G1 GC在并发标记阶段使用的增量式的标记算法。
- 并发标记是并发多线程的,但并发线程在同一时刻只扫描一个分区。
-
-
G1相对于CMS的优势:
- G1在压缩空间方面有优势;
- G1通过将内存空间分成区域(Region)的方式避免内存碎片问题;
- Eden、Survivor、Old区域不在固定,在内存使用效率上来说更灵活;
- G1可以通过设置预期停顿时间(Pause Time)来控制垃圾收集时间,避免应用雪崩现象;
- G1在回收内存后马上同时做合并空闲内存的工作,而CMS默认是在STW(stop the world)的时候做;
- G1会在Young GC中使用,而CMS只能在Old区使用。
-
G1的适合场景:
- 服务端多核CPU、JVM内存占用较大的应用;
- 应用在运行过程中会产生大量内存水平的、需要经常压缩空间;
- 想要更可控、可预期的GC停顿周期;防止高并发下应用的雪崩现象。