CMS(Concurrent Mark Sweep)收集器是 Java 虚拟机中的一种老年代垃圾收集器,它使用标记-清除(Mark-Sweep)算法进行垃圾收集。与传统的 Serial 和 Parallel 收集器不同,CMS 收集器主要关注减少应用程序的停顿时间,特别适用于需要响应性更强的应用场景。
CMS 收集器的特点和优势
-
并发标记:
CMS 收集器通过多线程并发标记,不会在整个标记阶段暂停应用线程。它通过在应用程序运行的同时标记存活对象,来尽可能减少应用程序的停顿时间。 -
增量更新:
CMS 在标记阶段使用增量更新技术,即在标记的同时,允许应用程序继续运行,并且会周期性地处理一些增量更新的任务。这样可以在标记阶段尽可能减少长时间的停顿。 -
老年代收集:
CMS 主要针对老年代进行垃圾收集,因为在大多数情况下,老年代的对象生命周期更长,产生的垃圾更多,而且更难处理。 -
响应性:
CMS 的设计目标是减少长时间停顿,提高应用程序的响应性。它特别适用于需要快速响应用户请求或需要短暂停顿的应用程序。
CMS 收集器的工作过程
CMS 收集器的工作流程大致如下:
-
初始标记阶段(Initial Mark):
CMS 收集器会暂停应用程序,标记所有的根对象,并标记直接可达的对象。这个阶段的停顿时间非常短。 -
并发标记阶段(Concurrent Mark):
在应用程序继续运行的同时,CMS 收集器会并发地标记所有可达对象,以识别出哪些对象是存活的。 -
重新标记阶段(Remark):
CMS 收集器会在标记阶段结束后进行最终的标记,以处理在并发标记期间发生的对象引用变化。这个阶段会短暂暂停应用程序。 -
并发清除阶段(Concurrent Sweep):
在应用程序继续运行的同时,CMS 收集器会并发地清除未标记的对象,并释放它们占用的内存空间。
CMS 收集器的缺点
尽管 CMS 收集器在减少停顿时间方面有显著优势,但它也有一些缺点:
-
内存碎片:
CMS 使用标记-清除算法,清除过程会产生大量的内存碎片,可能影响到大对象的分配和效率。 -
CPU 资源消耗:
CMS 在并发标记和清除过程中会消耗一定的 CPU 资源,可能会对应用程序的吞吐量产生一定的影响。 -
并发模式失败:
在特定情况下,CMS 可能会因为并发失败而导致停顿时间变长(比如内存不足或者更新引起的并发失败)。
使用 CMS 收集器
要在 Java 应用程序中使用 CMS 收集器,可以通过以下 JVM 参数来启用它:
java -XX:+UseConcMarkSweepGC MyApp
你也可以结合其他参数来优化 CMS 收集器的性能,例如设置最大停顿时间、触发 Full GC 的周期等。在一些老旧的应用程序中,CMS 收集器仍然是一种常用的选择,特别是对于那些需要快速响应用户请求的应用程序来说。