
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
我们在前几期的文章中给大家简单介绍了Java程序员需要掌握的一些垃圾回收机制应用等基础知识,而本文我们就再来说说,CMS收集器遗留的问题都有哪些。
CMS收集器开辟了一条垃圾收集的新思路,不过这么好的垃圾收集器却一直没有被Hospot虚拟机纳入到默认的垃圾收集器,到Jdk8使用的默认收集器都还是Parallelscavenge和Parallelold,这其中非常重要的原因就是CMS遗留了几个比较头疼的问题。
1、浮动垃圾
在并发清理阶段因为需垃圾收集线程是和用户线程同时执行任务的,这个时候用户线程运行时产生的垃圾是无法在当前阶段进行回收的,所以这段时间用户线程产生的新垃圾只能遗留到下一次收集,这些在垃圾收集过程中新产生的垃圾我们称为浮动垃圾。
3、空间碎片整理造成卡顿
CMS在平常情况下会使用标记清除法进行回收,只有在老年代的空间碎片达到一定程度,这个时候就会使用标记整理法对内存的空间碎片进行整理,因为标记整理的过程需要移动对象的位置,所以这个过程只能Stoptheword,这个时候内存越大那么这个收集时间就越长,造成这种卡顿现象。
4、可能导致系统长时间的假死。
因为在并发清除阶段会有新的对象产生,在有担保机制的情况下,当新生代垃圾清理的时候存活的对象大多,导致Survior区无法容纳全部的对象,这时就会触发担保机制,这里存活的对象里面会有一部分会直接进入老年代,所以在每次GC的时候老年代需要预留一部分内存出来,所以通常CMS在老年代占用了大概百分之七八十的时候就进行FullGC。
不过这段时间的产生对象的总体大小是未知的,如果新生代存活的对象非常多,这些担保的对象转移到老年代的时候可能导致老年代预留的空间也不足以容纳,那么此时CMS不得不进行一次Stoptheword的FullGC,因为此时堆空间已经完全占满,这个时候已经无法使用并发的清理方式进行收集了,所以此时只能停止用户线程来专心进行垃圾收集,而这时候老年代收集器不得不从CMS切换成Serialold垃圾收集器来进行垃圾收集。
至于这里为什么要使用单线程的Serialold,而不选择多线程的ParallelOld,那是因为CMS的新生代收集器是ParNew,而ParNew只能与CMS和SerialOld配合),所以这也是个无奈的选择。而切换成Serialold来进行垃圾收集的时候就有问题了,Serialold收集器是单线程的,它只适用于内存大小在几十到上百M的大小,而往往我们现在的内存大小都是几G到几十G,所以这种情况下整个垃圾收集的时间可能会特别特别长,有时候可能达到几个小时甚至好几天的都有可能。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei456学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。