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