🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。
✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!
🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客
🔥温馨提示:划到文末发现专栏彩蛋 点击这里直接传送
🔥本篇概览:详细讲解了CMS 收集器:低延迟——垃圾收集器6,并详细讲解了其工作的四大步骤。🌈⭕🔥
【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】
🌈章节引出:
前一篇章:
🌈章节速览:
16.5.1 CMS收集器介绍
CMS(Concurrent Low Pause Collector【并发低停顿收集器】)是JDK1.4.2开始引入的新GC 算法,在 JDK5 和JDK6中得到了进一步改进,它的主要适合场景是对响应时间的需求大于对吞吐量的要求。CMS垃圾收集器在强交互应用中几乎可认为有划时代意义。它是HotSpot虚拟机中第一 款真正意义上的并发收集器,第一次实现了让垃圾收集线程与用户线程同时工作。
CMS收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间。停顿时间越短,延迟就越低,就越适合与用户强交互的程序,因为良好的响应速度能更好地提升用户体验。
目前很大一部分的Java应用集中在互联网站或者B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望减少系统停顿时间,以给用户带来较好的使用体验。CMS收集器就非常符合这类应用的需求。
CMS的垃圾收集算法采用标记-清除算法,并且也会STW。不幸的是,CMS作为老年代的收集器,却无法与新生代收集器 Parallel Scavenge配合工作,所以在JDK1.5 中使用 CMS 来收集老年代的时候,新生代只能选择ParNew 或者Serial 收集器中的一个。
16.5.2 CMS的工作原理
CMS整个过程比之前的收集器要复杂,整个过程分为4个主要阶段,即初始标记阶段并发标记阶段、重新标记阶段和并发清除阶段,如图16-13 所示。
(1)初始标记(Initial-Mark)阶段:
在这个阶段中,程序中所有的工作线程都将会因为STW 机制而出现短暂的暂停,这个阶段的主要任务仅仅只是标记出GC Roots 能直接关联到的对象。一旦标记完成之后就会恢复之前被暂停的所有应用线程。由于直接关联对象比较小,所以这里的速度非常快。
(2)并发标记(Concurrent-Mark)阶段:
从GCRoots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。
(3)重新标记(Remark)阶段:
由于在并发标记阶段中,程序的工作线程会和垃圾收集线程同时运行或者交叉运行,为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,需要一次重新标记操作,通常这个阶段的停顿时间会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短。
(4)并发清除(Concurrent-Sweep)阶段:
此阶段清理已经被标记为死亡的对象,释放内存空间。由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。尽管CMS收集器采用的是并发回收,但是在其初始化标记和再次标记这两个阶段中仍然需要执行 STW 机制暂停程序中的工作线程,不过停顿时间并不会太长,因此可以说明目前所有的垃圾收集器都做不到完全不需要 STW,只是尽可能地缩短停顿时间。
由于最耗费时间的并发标记与并发清除阶段都不需要暂停工作,所以整体的回收是低停顿的。
另外,由于在垃圾收集阶段用户线程没有中断,所以在CMS回收过程中,还应该确保应用程序用户线程有足够的内存可用。因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,而是当堆内存使用率达到某一值时,便开始进行回收,以确保应用程序在CMS 工作过程中依然有足够的空间支持应用程序运行。要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启动后备预案:临时启用 Serial Old 收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。
CMS 收集器的垃圾收集算法采用的是标记-清除算法,这意味着每次执行完内存回收后,由于被执行内存回收的无用对象所占用的内存空间极有可能是不连续的一些内存块,不可避免地将会产生一些内存碎片,如图所示,图中清理完内存之后零碎的小内存区域就是所谓的内存碎片。
那么 CMS在为新对象分配内存空间时,将无法使用指针碰撞(BumpthePointer)技术,而只能够选择空闲列表(FreeList)执行内存分配。
有人会觉得既然标记-清除会造成内存碎片,那么为什么不把算法换成标记-压缩呢?答案其实很简单,要保证用户线程能继续执行,前提是它运行的资源(比如内存占用)不受影响。当CMS并发清除的时候,原来的用户线程依然在使用内存,所以也就无法整理内存。标记一压缩算法更适合在 STW 这种场景下使用。
优点:
CMS 的优点是并发收集和低延迟。
缺点:
CMS的缺点也很明显。
(1)会产生内存碎片,导致并发清除后,用户线程可用的空间不足。在无法分配大对象情况下,不得不提前触发 FullGC。
(2)对CPU资源非常敏感。在并发阶段,它虽然不会导致用户停顿,但是会因为占用一部分线程而导致应用程序变慢,总吞吐量会降低。
(3)由于在垃圾收集阶段用户线程没有中断,要是CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败而导致另一次 Full GC 的产生。
(4)无法处理浮动垃圾。在并发清除阶段由于程序的工作线程和垃圾收集线程是同时运行或者交叉运行的,那么在并发清除阶段如果产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有被及时回收,从而只能在下一次执行GC时释放这些之前未被回收的内存空间。
16.5.4 JDK后续版本中CMS的变化
【废除】
2017年JDK9中,G1变成了默认的垃圾收集器,替代了CMS。
2020年3月,JDK14发布,该版本彻底删除了CMS垃圾收集器。
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
热门专栏推荐
🌈🌈计算机科学入门系列 关注走一波💕💕
🌈🌈CSAPP深入理解计算机原理 关注走一波💕💕
🌈🌈微服务项目之黑马头条 关注走一波💕💕
🌈🌈redis深度项目之黑马点评 关注走一波💕💕
🌈🌈JAVA面试八股文系列专栏 关注走一波💕💕
🌈🌈JAVA基础试题集精讲 关注走一波💕💕
🌈🌈代码随想录精讲200题 关注走一波💕💕
总栏
🌈🌈JAVA基础要夯牢 关注走一波💕💕
🌈🌈JAVA后端技术栈 关注走一波💕💕
🌈🌈JAVA面试八股文 关注走一波💕💕
🌈🌈JAVA项目(含源码深度剖析) 关注走一波💕💕
🌈🌈计算机四件套 关注走一波💕💕
🌈🌈数据结构与算法 关注走一波💕💕
🌈🌈必知必会工具集 关注走一波💕💕
🌈🌈书籍网课笔记汇总 关注走一波💕💕
📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!