doc: 阅读cms文档

This commit is contained in:
asahi
2025-12-02 23:23:19 +08:00
parent 9f51f13801
commit db552403d2

View File

@@ -47,6 +47,8 @@
- [GCTimeRatio](#gctimeratio)
- [Serial Old](#serial-old)
- [Parallel Old](#parallel-old)
- [CMS收集器](#cms收集器)
- [CMS缺陷](#cms缺陷)
# 深入理解java虚拟机
@@ -389,4 +391,33 @@ Parallel Old主要是和Parallel Scavenge搭配使用否则Parallel Scavenge
> 在Parallel Scavenge/Parallel Old搭配使用时发生GC时用户线程也都处于暂停状态。
#### CMS收集器
CMSConcurrent Mark Sweep是一种`以获取最短回收停顿时间`的收集器。在重视服务响应时间的应用中适合使用CMS收集器进行老年代的垃圾回收。
从名字上可以看出CMS收集器基于`标记-清除`算法实现,其运作过程相对于前面集中收集器来说更加复杂,其分为如下步骤:
- 初始标记STW
- 初始标记仅仅会标记GC Roots能够直接关联到的对象速度很快
- 并发标记:
- 并发标记阶段会执行GC Roots Tracing
- 重新标记STW
- 重新标记期间会修正并发标记期间因用户线程继续运作而导致标记产生变动的那一部分对象的标记记录
- 该阶段的耗时比初始标记长,但是远比并发标记短
- 并发清除
在CMS的整个收集过程中初始标记和重新标记阶段是存在STW的但是并发标记和并发清除时收集器线程可以和用户线程同时运行。
<img src="https://cdn.tobebetterjavaer.com/stutymore/gc-collector-20231228211056.png" alt="" tabindex="0" loading="lazy" photo-swipe="" style="cursor: zoom-in;">
##### CMS缺陷
CMS虽然在垃圾收集时能够做到停顿时间较短但是其仍然存在如下缺陷
- CMS对CPU资源比较敏感。`CMS默认启动的回收线程数是CPU数量 + 3/4个当cpu物理核心数较少时垃圾收集线程将会抢占大量cpu资源`
- CMS无法处理浮动垃圾由于CMS在并发清理阶段并不会引入STW故而此时用户进程可以运行并伴随新的垃圾产生。该部分垃圾cms无法进行处理只能等待下一次GC来清掉。
- 由于在并发清除阶段同时还有用户线程运行,必须为用户线程预留内存,`故而CMS无法在老年代空间几乎被填满后才进行垃圾收集``需预留一部分空间以供并发收集时用户线程使用`
- 在JDK 1.6中CMS收集器的启动阈值提升到了92%,要是预留的内存没有办法满足用户线程的运行需要,`会出现Concurrent Mode Failure`,此时虚拟机将执行后备方案`临时启用Serial Old收集器重新进行老年代的垃圾收集`
- 故而`-XX:CMSInitiatingOccupancyFraction`参数设置过大时,容易产生大量`Concurrent Mode Failure`,性能反而降低
- CMS是一款基于标记-清除算法的老年代垃圾收集器,故而在收集结束时会有大量的内存碎片产生
- 为了解决内存碎片问题CMS提供了`-XX:+UseCMSCompactAtFullCollection`开关参数默认是开启的用于在CMS进行full gc时开启内存碎片的合并过程
- 但是每次full gc都进行内存碎片合并会导致等待时间过长故而引入了另一个参数`-XX:CMSFullGCsBeforeCompaction`该参数用于限制执行多少次不压缩的full gc后再执行一次带压缩的默认为0代表每次进入fullgc后都进行碎片整理