乐趣区

关于java:jvm-CMS收集器

CMS 是基于标记 - 革除算法的,收集的时候分为 4 个步骤:

  1. 初始标记
  2. 并发标记
  3. 从新标记
  4. 并发革除

# 初始标记
初始标记仅仅只是标记一下 GC Roots 能间接关联到的对象,所以速度很快。比方下图,这边的 GC Roots 只用了虚拟机栈为例。两个虚拟机栈分表创立了对象 OBJ_A1 和 OBJ_B1,他们也各有本人的其余援用,在这个阶段,他只会标记 OBJ_A1 和 OBJ_B1,其余的援用是不标记的,所以只管这个阶段有 STW,然而标记的数量少,工夫很快,根本不影响。

并发标记

并发标记就是依据初始标记的对象所间接或间接援用的对象进行标记,比方下图对 OBJ_A2,OBJ_AN 进行并发标记。这个阶段并没有 STW,所以能够创建对象,新增新的援用,也会让某些对象失去援用,比方下图,OBJ_B1 曾经变成垃圾了,OBJ_C1 是新增存活的对象。这个阶段因为对老年代所有的对象进行跟踪,所以是十分耗时的。

从新标记

在并发标记中,咱们看到存活对象 OBJ_C1 等以及垃圾对象 OBJ_B1 等是没有被标记进去的,所以这个阶段就是对这些对象进行从新标记。
这个阶段也有 STW,然而仅仅对并发标记中有变动的对象进行标记,这些数量比拟少,所以速度也是很快。

并发革除

这个阶段,就是在从新标记后,对垃圾对象的清理,和并发标记一样,都很耗时,因为并没有 STW,所以对程序的运行影响不大。CMS 采纳的是标记与革除算法。

毛病

CMS 的 4 个阶段,初始标记和从新标记须要 STW,然而工夫短,影响不大。并发标记和并发革除不须要 STW,尽管耗时,然而并发执行的,影响也不大,看起来 CMS 很完满,然而他也有一些毛病。

CPU

CMS 默认启动的回收线程数是(CPU 数量 +3)/ 4,也就是当 CPU 在 4 个以上时,并发回收时垃圾收集线程不少于 25% 的 CPU 资源,并且随着 CPU 数量的减少而降落。比方服务器是 2 核 4G,那就须要用(2+3)/4= 1 个线程去解决并发的标记和并发革除,这时候只剩下 1 个线程解决其余事件。

浮动垃圾

浮动垃圾的产生,次要是在并发清理阶段。从新标记后,CMS 垃圾回收器会晓得哪些须要清理,在并发清理阶段,他就清理从新标记后的垃圾对象,这个阶段并没有 STW,所以有可能产生新的对象,比方下图的 OBJ_N,创立完后,栈帧被回收,援用就没了,他在这个阶段是不能被革除的,只能等下一次垃圾回收的时候,被标记并革除。
如果这个阶段进入老年代的对象超过了残余空间,就会呈现 Concurrent Mode Failure 失败,那虚构机会长期启用 Serial Old 收集器进行老年代的垃圾收集。
能够用 XX:CMSInitiatingOccupancyFraction 设置老年代空间被占用多少百分比触发 CMS 回收,JDK1.6 后默认 92%。

空间碎片

jvm – 垃圾收集算法提过,标记 - 革除算法会产生空间碎片的,如果间断的内存空间不够寄存行将进入老年代的对象,此时就会触发 Full GC。
为了防止这种状况,CMS 收集器提供了一个 -XX:+UseCMSCompactAtFullCollection,默认关上的,当 Full GC 实现后,他会 STW,进行内存整理,把存活的对象严密的靠在一起,腾出间断空间。
如果每次都要从新内存,那都会 STW,所以 CMS 还提供了 -XX:CMSFullGCsBeforeCompaction 参数,默认是 0,他的意思是进行了多少次 Full GC 后才整顿内存。

退出移动版