CMS(Concurrent Mark Sweep)收集器是一种以减少停顿时间(STW,Stop-The-World)为目标的垃圾收集器,主要用于处理老年代的垃圾回收任务,适用于对延迟敏感的应用场景,如Web服务器。以下是CMS收集器的工作原理和特点:
工作原理
CMS收集器的工作流程可以分为以下几个阶段:
- 初始标记(Initial Mark):标记从GC Roots直接可达的对象。这个阶段会短暂地暂停所有应用线程,但耗时很短。
- 并发标记(Concurrent Mark):在初始标记完成后,CMS开始并发地标记剩余的对象,即从GC Roots开始遍历整个对象图,标记所有可达的对象。这个阶段是与应用程序并行执行的,不会停止应用线程。
- 重新标记(Remark):由于在并发标记阶段,应用线程还在继续运行,可能导致一些新的对象变得可达,因此需要重新标记这些新对象。这个阶段也会短暂暂停应用线程,但耗时较短。
- 并发清除(Concurrent Sweep):在重新标记后,CMS开始并发地清除未被标记的对象,释放内存空间。这个阶段同样是与应用程序并行执行的,不会停止应用线程。
优点
- 并发收集:CMS收集器的大部分工作是与应用程序并发执行的,这减少了应用程序的停顿时间,对于需要低延迟的应用来说是一个很大的优势。
缺点
- 内存碎片:CMS收集器使用标记-清除算法,这会导致内存碎片的产生。随着JVM的长时间运行,碎片化会越来越严重,只有通过Full GC才能完成整理。这可能导致在无法分配大对象的情况下,不得不提前触发Full GC。
- CPU资源敏感:在并发阶段,CMS虽然不会导致用户停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。
- 无法处理浮动垃圾:在并发标记阶段,如果产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有被及时回收,从而只能在下一次执行GC时释放这些之前未被回收的内存空间。
内存碎片处理
CMS收集器的主要问题是碎片化,因为它使用的是Sweep而不是Compact。随着时间的推移,碎片化会越来越严重,只有通过Full GC才能完成整理。CMS提供了CMSScavengeBeforeRemark
参数,用来保证Remark前强制进行一次Minor GC,以减少因新生代对象过多而导致的长时间Remark阶段。
综上所述,CMS收集器在减少停顿时间方面表现出色,但同时也带来了内存碎片和CPU资源敏感等问题。在实际应用中,需要根据应用的具体需求和特点来选择是否使用CMS收集器,并进行相应的调优。