一般我们老年代的垃圾收集器都是使用的CMS(Concurrent Mark Sweep)。CMS使用的是标记-清理算法,工作流程大致是先标记需要回收的对象,然后回收垃圾,最后将存活的对象整理到一边,防止出现太多的内存碎片。有人说这不就是标记-整理算法吗,但是标记整理算法的步骤是先标记需要回收的对象,然后将存活的对象整理到一边,最后才将端边界之外的可回收对象清理。
因为在垃圾收集的时候,必然会产生“Stop the World”时间,让系统短暂不可用,所以CMS垃圾回收器采取的是垃圾回收线程和工作线程尽量同时执行的模式,减少系统的停顿。
CMS垃圾收集器分为4个阶段
- 初始标记
这个阶段需要STW(Stop the World),会停止所有的工作线程,然后标记所有GC Roots直接引用的对象,一般方法的局部变量和类的静态变量是GC Roots。这个阶段虽然会停止工作线程,但是标记GC Roots直接引用的对象速度非常块,所以影响很小。
- 并发标记
这个阶段工作线程和垃圾回收线程会一起工作,工作线程不停的创造新的对象,也有一些存活的对象失去引用,变成了垃圾对象,垃圾回收线程会将那些GC Roots可达的对象都标记出来。这个阶段是最耗时的阶段,因为是对老年代所有的对象进行GC Roots追踪,但是因为工作线程也在同时运行,所以不会让系统停顿。
2.5.并发预清理
这个阶段其实是为了给重新标记阶段减少工作量,此阶段标记从新生代晋升的对象、新分配到老年代的对象以及在并发阶段被修改了的对象。那如果老年代的对象引用到了新生代的GC Roots,如何来判断这个对象是否是存活的对象呢ÿ