一张图看懂CMS垃圾回收器的底层原理
CMS使用的是标记清除算法,真正做到了并发
标记”是指将存活的对象和要回收的对象都给标记出来,而“清除”是指清除掉将要回收的对象。
四个步骤
1、初始标记(CMS initial mark)。
2、并发标记(CMS concurrent mark)。
3、重新标记(CMS remark)。
4、并发清除(CMS concurrent sweep)。
核心原理
优缺点和适用场景
优点:用户线程和GC线程同时运行,减少用户线程阻塞的时间。
a.CMS收集器初始化标记与重新标记只需要短暂的stw操作,不会非常耗时。
b.CMS收集器降低GC线程在清理垃圾过程中,对用户线程暂停的时间。
c.CMS收集器可以实现用户线程与GC线程同时执行,整体可以实现低延迟。
缺点:
a.标记清除算法会产生内存碎片化
b.与用户线程同时执行,消耗CPU资源
c.无法处理浮动垃圾(原先有引用,后来没引用,只能等待下次垃圾回收)
d.用户线程空间不足,无法存放大对象的情况下,可能会触发FullGC
适用场景:互联网站或者B/S系统的服务器端上,大型服务器等
为什么CMS收集器采用标记清除而不是标记整理算法
为了保证用户线程与GC线程同时运行,所以采用标记清除算法,
如果采用标记整理算法,有可能会导致移动内存地址,会发生的stw问题。
参数设置
"-XX:+CMSScavengeBeforeRemark":开启在CMS重新标记阶段之前的清除minor gc,能防止新生代很多,导致重新标记耗时太长。
"-XX:+UseConcMarkSweepGC":开启CMS收集器【会自动将UseParNewGc打开】
"-XX:+CMSConcurrentMTEnabled":启动CMS多线程执行
"-XX:ConcGCThreads":指定CMS启动线程个数,(例如:-XX:ConcGCThreads=4)
"-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70":设置堆内存使用率的阈值,一旦达到该阈值便开始回收垃圾。【JDK5是68,JDK6及以上是92】
"-XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0": 执行多少次fullgc后执行一次full gc的标记压缩算法,0标识每次full gc(标记清除)后都会压缩