CMS
CMS是一个hotspot划时代的垃圾收集器,它是一个并发的垃圾收集器,也就是说GC线程是可以和用户线程一起运行,如图所示
可以看到CMS主要分为以下几个阶段:
- 初始化标记
- 并发标记
- 重新标记
- 并发清理
- 重置线程
对于以上阶段只有初始化标记和重新标记是STW的,其他阶段都是并发的,那么这个过程中肯定会存在一些问题,因为用户线程和GC线程是一起运行的。
1、初始化标记
这阶段只扫描跟GC-ROOTS关联的对象,这个过程很快,常见的初始化标记GC-ROOTS对象有:局部变量、常量、静态属性、JNI引用、以及跨代引用的对象
2、并发标记
这个过程是并发的所以不存在STW的问题,但是跟用户线程共存,难免有两个问题,漏标以及浮动垃圾的问题,CMS使用三色标记+增量更新处理并发标记时垃圾的问题,但是没有解决浮动垃圾的问题,因为增量更新只处理白色对象被一个黑色对象所引用,这时候会将黑色对象重置为灰色,可以认为是关注引用的增加。
3、重新标记
重新标记,这个过也是STW,但是时间也不会太长,比并发标记短多了,这个过程主要处理漏标的问题
4、并发清理
并发清理阶段也是不需要STW的,但是正是因为如此这个阶段也会产生浮动垃圾,这也是CMS使用标记-清除算法的原因,也导致了内存碎片的问题。
5、重置线程(略)
G1
因为CMS存在的问题,hotspot推出了G1,G1在回收时会优先回收效率高的,这也是名字的由来,同时支持可预测的停顿时间,当然这不能乱设置,否则会导致频繁GC,G1在物理上没有了年轻代和老年代的划分,都是一个个的region,局部采用复制算法,全局来看是采用标记-整理算法。主要分为以下几个阶段:
可以看到G1主要分为以下几个阶段:
- 初始化标记
- 并发标记
- 最终标记
- 筛选回收
- 重置线程 G1的流程和CMS大致相同,以下我们具体分析一下:
1、初始化标记
和CMS一致
2、并发标记
这个阶段和CMS一样也是不需要STW的,G1使用三色标记+原始快照,来解决漏标问题,SATB会在开始生成一个快照(bitmap),认为这个快照里面的对象都是存活的,后续如果引用发生了删除,会将这个引用关系,推送到GC的堆栈上,保证这个对象还能被找到,但即使这个是这对象已经是垃圾了,还是会标记为黑色,也就是说这里还是会有浮动垃圾。
3、最终标记
和CMS一致
4、筛选回收
这一步也是G1的名称的由来,它会对垃圾进行排序,优先回收效率最高,然后尽量的满足你的停顿时间,然后这个阶段是STW的所以这里不存在浮动垃圾的的问题
5、重置线程
总结
- CMS确实是一个划时代的产物,它是第一个并发的垃圾回收器,但是遗留了几个问题 内存碎片、浮动垃圾,如果空间不够,将会使用Serial,这时候全程STW,所以不会等到老年代空间完全使用后才进行GC。
- G1对CMS存在的问题进行了进一步的优化 ,解决了内存碎片以及一部分的浮动垃圾的问题