cms垃圾回收器,用于回收老年代内存空间,官方号称零停顿(其实也会停顿,不过垃圾回收中,比较 耗时的部分采用了和服务线程一起工作的方式来减少停顿),该垃圾回收器默认会搭配ParNew(用于 收集年轻代的内存空间)垃圾回收器使用。年轻代使用复制算法,同时是并发的方式;老年代采用标记 清除的方式,也是并发的方式,会利用服务器多核心的优势。该垃圾回收器主要是为了避免老年代垃圾回收的长停顿而设计的。
主要通过两种方式:
1、老年代不进 行空间的整理,而是采用空闲列表的方式来管理空用的内存。
2、标记和清除部分时间比较长的阶段都 是和服务运行同时进行的,这一部分不会造成stop the world。然而虽然不会造成服务的stop the world,但是当垃圾回收的时候,必然会跟服务争抢cpu资源,导致总体的吞吐量降低。默认情况下, 垃圾回收的线程数是服务器的核心数+3的四分之一,比如说一般的电脑4核心,默认会开启一个垃圾回 收的线程,相当于在比较极端的情况,会抢占25%的cup资源
启用该回收器,使用jvm参数: -XX:+PrintGCDetails -Xmx20M -Xms20M - XX:+UseConcMarkSweepGC
这里不指定年轻代使用的垃圾回收器的话会默认使用ParNew 垃圾回收器,相当于serial new 的并发版本。
package cn.yishijie.jvm;
import java.util.concurrent.TimeUnit;
public class ClassFile {
public static void main(String[] args) throws Exception{
while (true){
byte[] b = new byte[1024*1024*3];
TimeUnit.SECONDS.sleep(1000);
}
}
}
等一段时间发现打印处日志:
[GC (Allocation Failure) [ParNew: 2066K->640K(6144K), 0.0018567 secs] 12306K- >10918K(19840K), 0.0019070 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
可以发现这里的年轻代确实是使用了ParNew垃圾回收器。
GC (Allocation Failure):年轻代内存分配失败,触发这一次垃圾回收
ParNew: 2066K->640K(6144K), 0.0018567 secs:年轻代使用的垃圾回收器名称为ParNew,年轻代垃 圾回收之前的使用的内存大小,年轻代垃圾回收之后使用的内存大小,总的年轻代的大小。 0.0018567 secs:该次垃圾回收耗时
12306K->10918K(19840K), 0.0019070 secs]: gc前总的堆使用大小,gc后总的堆使用的大小,整个堆 的大小 0.0019070 secs:gc耗时
[Times: user=0.00 sys=0.00, real=0.00 secs] : 此次垃圾回收使用的时间,系统调用或等待事件耗用 的时间,总的运用停顿的时间。
通过加大对象的大小,让对象直接分配到老年代,压老年代的空间,触发cms的回收动作:
package cn.yishijie.jvm;
import java.util.concurrent.TimeUnit;
public class ClassFile {
public static void main(String[] args) throws Exception{
while (true){
byte[] b = new byte[1024*1024*10];
TimeUnit.SECONDS.sleep(1000);
}
}
}
初始标记:会stop the world
[GC (CMS Initial Mark) [1 CMS-initial-mark: 10240K(13696K)] 14493K(19840K), 0.0009010 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
并发标记:不会stop the world
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.000/0.000 secs]