CMS垃圾回收器Preclean阶段

40 阅读3分钟

CMS (concurrent Mark Sweep)

cms垃圾回收器具有以下阶段

  • 初始标记阶段(Initial Mark Phase) 这是一个短暂的停顿阶段,会标记出所有可达的存活对象,并标记被引用的对象的根节点。是并发标记的起点
  • 并发标记阶段(Concurrent Mark Phase) 在这个并发阶段,垃圾回收器会并发的遍历堆中对象,标记所有存活的对象。这个阶段与应用程序同时进行
  • 预清理阶段(Preclean Phase) 在并发标记以后,CMS会进行预清理。在这个阶段,垃圾回收器会重新并发的扫面在并发标记期间被更新的对象,以减少以下阶段的工作量
  • 重新标记阶段(Remark Phase) 这是一个停顿阶段。在这一阶段,垃圾回收器会暂停应用程序的执行,重新遍历堆中对象。目的是标记那些在并发标记过程中新增或修改的存活对象
  • 并发清楚阶段(Concurrent Sweep Phase) 垃圾回收器会并发的清理所有标记为垃圾的对象,释放其占用的内存。这一阶段会与应用程序同时进行。

在CMS执行的整个过程中,除了初始标记和重新标记阶段,大部分都是并行的,以最大程度减少对应用程序性能的影响。

关于PreClean阶段

首先,在并发标记阶段,垃圾回收器标记所有的存活对象,但是在标记的过程种,由于应用程序的并发操作,可能导致部分对象在标记完成前被更新,例如从年轻代晋升的对象、新分配到对象以及并发标记过程中被mutators更新的对象。为了保证标记的准确性和完整性,CMS引入了预清理阶段。 在预清理阶段,垃圾回收器会识别并标记那些在并发标记过程中发生了变化的对象,并将其标记位dirty。这样在进入下一阶段后,只需要关注被标记为dirty的对象,而无需扫描整个堆,从而减少下一个阶段的工作量。

CMSMaxAbortablePrecleanTime

这是一个JVM启动参数,用于设置CMS在预清理阶段中可以中止的最大时间。

由于预清理阶段会重新扫描并发标记过程中被更新的对象,这个过程可能占用较长的时间,如果超过了预先设置的最大时间限制,那么垃圾回收器就会终止预清理阶段,转而开始执行重新标记。

默认情况下,参数值为0,也就是预清理阶段没有时间限制。


参考文献:

[1]: 8 Concurrent Mark Sweep (CMS) Collector


附录:常见jvm参数

完整参数集

  • -Xms heap初始化内存
  • -Xmx heap最大内存
  • -Xmn 年轻代(young generation)初始化大小
  • -XX:MetaspaceSize 出发元数据空间第一次GC的阈值
  • -XX:MaxMetaspaceSize 元数据最大空间
  • -XX:MaxDirectMemorySize 用于NIO的最大堆外内粗
  • -XX:SurvivorRatio eden space 和survivor space的比例。默认8
  • -XX:+useConcMarkSweepGC 允许CMS回收器应用于老年代(old generation)。但应用该选项时,-XX:+useParNewGC也会自动打开。
  • -XX:+ExplicitGCInvokesConcurrent 允许System.gc()调用并行GC,需要-XX:+useConcMarkSweepGC
  • -XX:ParallelGCThreads 设置GC线程数
  • -XX:+CMSClassUnloadingEnabled 允许CMS在永久代(permanent generation)执行GC
  • -XX:CMSInitiatingOccupancyFraction 当老年代的空间使用率到达这个阈值时,JVM会触发Full GC
  • -XX:+UseCMSInitiatingOccupancyOnly 开启-XX:CMSInitiatingOccupancyFraction
  • -XX:CMSMaxAbortablePrecleanTime CMS中Preclean阶段的最长执行时间
  • -Xloggc 用于记录详细GC事件信息的文件路径。写入此文件的信息类似于使用-verbose:gc选项输出的信息。同时指定了-Xloggc-verbose:gc时,-Xloggc将覆盖-verbose:gc选项
  • -XX:+HeapDumpOnOutOfMemoryError
  • -XX:HeapDumpPath
  • -XX:+PrintGCDetails
  • -XX+PrintGCDateStamps