CMS垃圾回收器:低延迟
CMS垃圾回收器CMS工作原理CMS的特点CMS的优缺点CMS参数设置CMS在后续版本的变化
CMS垃圾回收器
在JDK5,HotSpot推出了一款在强交互应用中几乎可认为有划时代意义的垃圾收集器CMS(Concurrent Mark Sweep)收集器,这款收集器是HotSpot虚拟机中第一款真正意义上的并发收集器,他第一次实现了让垃圾收集线程与用户线程同时工作。
CMS收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时。停顿时间越短(低延迟)就越适合与用户交互的程序,良好的响应速度能提升用户体验。
目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以带给用户较好的体验。CMS收集器就非常符合这类应用的需求。
CMS的垃圾收集孙发采用标记清除算法,并且也会STW.
CMS作为老年代的收集器,却无法与JDK4中已经存在的新生代收集器Parallel Scavenge配合工作,所以在JDK5中使用CMS 来收集老年代的时候,新生代只能选择ParNew或者Serial 收集器中的一个。
在G1出现之前,CMS使用还是非常广泛的,一直到今天,仍然有很多系统使用CMS垃圾收集器。
CMS工作原理
CMS整个过程比之前的收集器更复杂,整个过程分为4个主要阶段。即初始标记阶段,并发标记阶段,重新标记 阶段和并发清除阶段。
CMS的特点
尽管CMS收集器采用的是并发回收(非独占式),但是在其初始化标记和在此标记这两个阶段中仍然需要执行STW机制暂停程序中的工作线程,不过暂停时间并不会太长,因此可以说明目前所有的垃圾收集器都做不到完全不需要STW,只是尽可能缩短暂停时间。
由于嘴耗费时间的并发标记与并发清除阶段都不需要暂停工作,所以整体的回收是低停顿的。
另外,由于在垃圾收集阶段用户线程没有中断,所以在CMS回收过程中,还应该确保应用程序用户线程有足够的内存可用。因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了咱进行手机,而是当堆内存使用率达到某一阈值时,便开始进行回收,以确保应用程序在CMS工作过程中依然有足够的的空间支持应用程序运行。要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Comcurrent Mode Failure”失败,这时虚拟机将启动后备方案,临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿的时间就很长了。
CMS收集器的垃圾收集算法采用的是标记清除算法, 这意味着每次执行完内存回收后,由于被执行内存回收的无用对象所占用的内存空间极有可能是不连续的一些内存块,不可避免地将会产生一些内存碎片。那么CMS在为新对象分配内存空间时,将无法使用指针碰撞技术。而只能够选择空闲列表执行内存分配。
为什么CMS会产生内存碎片,不使用标记整理算法呢?
因为在并发清除的时候,用标记整理算法整理内存的话,原来的用户线程使用的内存地址就会发生变化。要保证用户线程能继续执行,前提是它运行的资源不收影响。标记压缩算法更适合STW这种场景下使用。
CMS的优缺点
优点
并发收集低延迟缺点
会产生内存碎片:导致并发清除后,用户线程可用的空间不足。在无法分配大对象的情况下,不得不提前触发Full GC.CMS收集器对CPU资源非常敏感。在并发阶段,他虽然不会导致用户停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。CMS收集器无法处理浮动垃圾: 可能出现 “Comcurrent Mode Failure” 失败而导致另一次Full GC.在并发标记阶段由于程序的工作线程和垃圾收集线程是同时运行或交叉运行的,那么在并发标记阶段如果产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有被及时回收,从而只能下一次执行GC时释放这些之前未被回收的内存空间。