Java基础之《JVM性能调优(9)—CMS垃圾回收器》

一、为什么会出现CMS垃圾回收器

1、由于历代垃圾回收器都是串行或独占式回收的,例如前面3个年轻代回收器(Serial、ParNew、Parallel) + 2个老年代回收器(Serial Old、Parallel Old),都是必须停止工作线程后,gc线程才开始垃圾清除。

2、在这样的大背景下,与2002年JDK1.4.2发布CMS,它是那个时代第一次实现并发收集器(相对来说),即实现了让垃圾收集线程与用户线程同时工作。

3、CMS的特色就是停顿时间短(低延迟),停顿时间越短就越适合用户交互的程序,越能提升用户体验。

4、在G1收集器面式之前,CMS基本都是JVM的标配,甚至是现在市面都是很多系统在使用CMS。

二、CMS如何让垃圾回收线程和用户线程同时工作
它设计了7个阶段,来保证并行工作。

三、CMS垃圾回收器原理1—初始标记

1、第一阶段:初始标记
Java基础之《JVM性能调优(9)—CMS垃圾回收器》_第1张图片

(1)先把所有工作线程挂起,所有工作线程进入安全点SafePoint后,当前处于STW状态。
(2)gc线程,采用多线程,从GCRoot 标记直接可达的对象(XYZ)。CMS是老年代回收器,所以只标记老年代的。
什么是直接可达?
从栈帧、方法区(静态变量、常量)、本地方法栈等,查找第一个引用对象。
例如:直接引用的对象都是(acdYZ),就被标记为直接可达。其他对象不标记。

四、CMS垃圾回收器原理2—并发标记

1、第二阶段:并发标记
Java基础之《JVM性能调优(9)—CMS垃圾回收器》_第2张图片

2、gc线程本阶段干什么?
通过遍历第一个阶段(初始标记)标记出来的存活对象,继续递归遍历老年代,并标记可直接或间接到达的所有老年代存活对象(J)。

3、工作线程本阶段干什么?
(1)工作线程的栈帧,继续生产新的对象,继续往eden区填对象。
在年轻代生产
(2)工作线程继续运行,旧的栈帧就出栈,出栈后老对象就死亡,即存活对象转变为垃圾对象。

由于该阶段工作线程还一直在生产新对象和老对象变成垃圾对象。
那这阶段新产生的对象和垃圾对象,如何处理?
(1)不处理?不处理的话就会遗漏,导致垃圾回收不干净。
(2)处理?处理的话,就非常复杂,要对整个老年代再重新GCRoots,重新标记,即费时又费力。

4、那有什么好的算法能快速解决?
JVM设计了一个cardtable来记录并发阶段老年代对象变更后的存储。

具体技术实现如下:
(1)先把内存划分为大小相同的Card(卡片),每个Card的大小为512Byte,每个Card可以装1个或多个对象。
Java基础之《JVM性能调优(9)—CMS垃圾回收器》_第3张图片

你可能感兴趣的:(JAVA基础,java)