CMS+ParNew
- 一块eden,两块survivor,一块old。
YGC
- ParNew。一次stw——复制。
- eden区和survivor1区活跃对象复制到survivor2,部分survivor1区对象晋升到老年代。
- 开始前。
- 结束后。
OGC
- CMS。两次stw——初始标记、重新标记。
- 老年代直接标记清除,没有复制压缩。
- 开始前。
- 结束后。
优缺点
- 优点:
- 并发高效。
- 缺点:
- 老年代标记清除碎片多。
- 停顿时间无上限。
G1
- 堆被分成多个大小的区域。映射为不连续的eden,survivor,old。
- YGC 1次stw——复制,Mixed GC 4次stw——初始标记、重新标记、清理、复制。
- 停顿时间瓶颈在复制上,未能在转移过程中准确定位对象地址。
- 无法在堆中申请新的分区时,执行STW的单线程Full GC。
YGC
- 年轻代复制存活对象到新的survivor。
- 存活对象用 Rset(记录其他region中的对象对本region对象的引用)标识,GC时不用扫描整个堆。
- 开始前。
- 结束后。
Mixed GC
- 并行标记清除不可达old,复制活跃的young和old。
- 标记清除old。
- 复制old+young。
- 结束后。
优缺点
- 优点:
- 最大停顿时间可预测。每次处理部分堆,实现停顿时间限制。
- 老年代也会复制,碎片有限。
- 缺点
- RememberedSet占据空间较多,5-20%
- 写屏障(在引用对象进行赋值时的切面),维护RememberedSet
Rset
- 为了每次GC只扫描部分老年代,需要记录old其他region的跨代引用,可达性分析的时候只扫描有跨代引用的老年代region
- 跨region引用的摘要,point-into数据结构,Map类型
- k:引用该young region的 old region地址
- v:该old的卡表-卡页索引,
CARD_TABLE[this address >> 9]
- 卡页:标记old的内存块中是否有对该young的引用,有则为脏卡页
- 卡页:标记old的内存块中是否有对该young的引用,有则为脏卡页
- 不保存来自young引用的原因: young的新对象多,基本所有region都会有待回收的对象,都需要遍历,没有必要用额外的空间维护reset
ZGC
- 不分代。
- 3次stw——初始标记、再标记、初始转移。
- 瓶颈为再标记,通常1ms以内。
- 2个技术点可在转移对象的过程中追踪对象最新的位置,从而做到并发转移。
- 着色指针(引用)。
- 对象存活信息记在引用中,而不是对象头。
- 使用3个bit标识3种视图和存活信息:M0,M1,Remapped。
- 读屏障。应用线程从堆中读取对象引用时触发。
- ZGC用来标记和转移过程中确定对象引用地址是否满足条件,并作出修改对象视图等操作。
- 着色指针(引用)。
过程
- 初始化。视图为Remapped。
- 标记阶段。
- 视图为Mo,标记之后活跃对象视图为M0,不活跃的为Remapped。
- 活跃对象地址存储在活跃对象信息表。
- 视图为Mo,标记之后活跃对象视图为M0,不活跃的为Remapped。
- 转移阶段。视图为remapped。
- 第二次GC标记阶段的活跃对象视图为M1,M0和Remapped均为不活跃对象。
优缺点
- 优点:
- 停顿时间短,通常1ms左右。
- 缺点:
- 吞吐量下降。
- 单代回收每次处理的对象更多。
- 读屏障cpu开销。
- 吞吐量下降。