31. 什么是CMS(Concurrent Mark-Sweep)垃圾回收器?它的优缺点是什么?
大约 4 分钟
CMS(Concurrent Mark-Sweep)垃圾回收器 是Java虚拟机(JVM)中的一种垃圾收集器,专门设计用于减少垃圾回收(GC)引起的应用程序停顿时间(Stop-the-World, STW)。CMS在JDK 1.4中引入,主要针对响应时间要求较高的应用程序,如Web服务器、金融系统等,对低延迟有较高要求的场景。
CMS垃圾回收器的工作原理
CMS垃圾回收器的工作过程分为以下几个主要阶段:
- 初始标记(Initial Mark):
- 作用:标记GC Roots直接可达的对象。
- 停顿时间:这一步需要暂停所有应用线程(STW),但标记只涉及少量对象,因此时间通常较短。
- 并发标记(Concurrent Mark):
- 作用:在应用程序运行的同时,CMS线程并发地从GC Roots开始,遍历整个对象图,标记所有可达的对象。
- 停顿时间:无需暂停应用线程,因此对应用程序性能影响较小。
- 重新标记(Remark):
- 作用:在并发标记过程中,应用程序仍然在运行,因此可能有对象的引用关系发生变化。重新标记阶段会再次暂停所有应用线程,修正标记过程中的遗漏。
- 停顿时间:这一步也是STW事件,但通过优化,该阶段的时间通常也较短。
- 并发清除(Concurrent Sweep):
- 作用:在应用程序继续运行的同时,CMS线程并发地清除标记阶段中未被标记的对象,回收其占用的内存空间。
- 停顿时间:无须暂停应用线程,对应用程序几乎没有影响。
CMS垃圾回收器的优点
- 低停顿时间:
- CMS的最大优势是能够显著减少应用程序的停顿时间。除了初始标记和重新标记两个短暂的STW阶段,其余工作都在应用线程并发运行,适合对响应时间要求高的应用。
- 并发执行:
- CMS大部分的垃圾回收工作是并发执行的,与应用线程同时进行,因此减少了对应用程序的性能影响。
- 适合大堆内存:
- 对于具有大堆内存的应用程序,CMS能够有效减少长时间的Full GC停顿,使得大内存应用更加流畅和高效。
CMS垃圾回收器的缺点
- 内存碎片:
- CMS使用标记-清除算法回收内存,虽然能够快速回收,但容易产生内存碎片。随着时间推移,内存碎片会导致大对象分配困难,进而触发Full GC,影响应用性能。
- Full GC开销大:
- 当内存碎片严重、老年代空间不足时,CMS可能无法完成并发清理任务,触发Full GC。Full GC会带来较长时间的应用停顿,严重影响系统的响应性。
- 内存占用较高:
- CMS在并发回收期间需要保留一部分内存供应用程序使用,同时也为垃圾回收线程保留了一部分内存空间,因此在高负载情况下,CMS的内存占用较高。
- 并发模式失败(Concurrent Mode Failure):
- 当CMS在并发清理阶段,老年代空间不足以容纳新对象时,会导致并发模式失败,系统将退回到单线程的Serial Old收集器进行Full GC,这会带来较长时间的停顿。
- 额外的CPU开销:
- CMS的并发回收过程占用CPU资源,特别是在多核环境下,CMS垃圾收集线程会与应用线程竞争CPU资源,可能导致系统整体性能下降。
配置CMS垃圾回收器
在JVM中启用CMS垃圾回收器,可以使用以下参数:
-XX:+UseConcMarkSweepGC
其他常用的调优参数包括:
线程数量:设置并发GC线程数(通常为CPU核心数的一半)。
-XX:ConcGCThreads=<num_of_threads>
并发模式失败阈值:设置CMS在并发回收过程中,老年代使用比例达到一定阈值时触发并发模式失败,退回Full GC。
-XX:CMSInitiatingOccupancyFraction=<percentage>
内存碎片整理:启用内存碎片整理以减少碎片化。
-XX:+UseCMSCompactAtFullCollection
总结
CMS(Concurrent Mark-Sweep)垃圾回收器 是一种专注于减少应用程序停顿时间的GC算法,适用于低延迟、高响应要求的应用程序,如在线服务、Web服务器等。尽管CMS能够显著降低GC引起的停顿,但其内存碎片问题、Full GC的高开销以及额外的CPU资源占用使得它在某些场景下不如其他现代GC(如G1、ZGC)适用。因此,在使用CMS时,需要结合具体应用场景进行调优,以充分发挥其优势并减小其不足的影响。