JVM垃圾回收二
并发标记,三色标记
并发标记:
程序一边执行,垃圾回收器一边进行标记
三色标记,CMS,G1都使用:
1.黑色 表示对象本身及子对象都被扫描过
2.灰色 表示对象本身被标记过
3.白色 未被扫描到的对象(表示与根对象不可达)
三色标记的问题
漏标记问题, 本不应该被回收的对象,被回收掉了
有个对象C, 被B引用, 还有个对象A
垃圾回收器1线程:扫描到A,标记A为黑色,
垃圾回收区2线程:扫描到B,标记B为灰色,此时还未扫描到B下的C对象,
---!!!!此时,A引用了C, B把C的引用变为NULL, 那么最终C就变成了白对象,然后被错误地回收了,当A操作C时会发生空指针
GC解决漏标记问题解决方案
1.CMS下的处理方案:
IncrementalUpdate ,关注增量, 即当A引用C的时候, A会变为灰对象,这样后续GC会再扫描A对象
2.G1下的处理方案
SATB(snapshot-at-the-beginning) 快照↓↓↓↓↓
即:初始标记时记录所有对象引用关系的快照,重新标记时再做一次快照,比较一下前后两次快照的差异,得出哪些对象引用有变动, 关注标记的删除
快照信息保存在GC的堆和栈中
G1回收器的技术细节
1.内存区域不固定,例如一个Eden区直接变为S区, S区可能直接变成old区..
2.跨代引用:老年代的对象引用了新生代对象,老年代对象会被视为ROOT对象
3.Rset(记忆集,记录于每个Eden区)与CardTable(卡表,记录跨代引用映射在哪块内存),避免ygc时扫描老年代
4.所以,堆空间小于6g时,不推荐使用G1,因为会有一些内存浪费于Rset
卡表的说明
安全点safepoint:优雅地stw
1.主动式中断:GC要开始工作STW业务线程时,业务线程要轮询 标识GCstart(0->1),跑到最近的安全点进行挂起
2.安全点的规范: class中的指令-->方法调用,循环跳转,异常跳转等
安全区域
线程操作中不对引用造成影响的区域
低延迟的垃圾回收器
垃圾回收器的三项指标: 1.内存占用 2.吞吐量 3.延迟 很难同时满足
Eplison:
"不干活"的垃圾回收器,不进行垃圾回收,主要用于性能测试,压力测试,调试用,看内存布局优化等,提供一些API
ZGC:类似于G1
1.可以控制在10ms的stw延迟
2.内存也会划分Region,但是不分代
3,使用ColoredPointers, 染色指针,即在对象引用指针中加入一些染色数据, 内存不可超过4TB
4.效率非常高
Shenandoah: 非Oracle开发,也是使用染色指针, 延迟可控制在100ms
GC日志
-XX:+PrentGCDetail 开启GC日志