### CMS收集器(Concurrent Mark Sweep)
**CMS收集器(Concurrent Mark Sweep) **是一种以获取最短回收停顿时间为目标的收集器
JDK1.5时,HotspotVM推出一款在强交互应用中可认为有划时代意义的垃圾收集器CMS(Concurrent-Mark-sweep)。CMS是HotspotVM中第一款真正意义上的并发垃圾收集器,第一次实现了让垃圾收集线程与用户线程可同时工作。
CMS关注点是尽可能缩短垃圾收集时用户线程的停顿时间,停顿时间越短就越适合与用户交互的场景。
CMS使用的是标记-清除算法,针对老年代的垃圾回收
无法与新生代垃圾回收器Parallell Scavenge组合使用,使用CMS时只能和ParNew或者时Serial配合使用。
JDK9中CMS被标记为废弃,JDK14中正式被移除
#### 特性
* 目标:获取最短回收停顿时间
* 适用于互联网B/S系统服务端
* 基于“标记-清除”算法实现
* 也称为并发低停顿收集器
* JDK1.5默认设置下CMS收集器当老年代使用了68%的空间后就会被激活
* JDK1.6CMS收集器的启动阈值提升至92%
* 如果CMS运行期间预留的内存无法满足应用程序需要,就会出现一次"Concurrent Mode Failure"失败,此时将启动后备预案:临时启用Serial Old收集器重新进行老年代的垃圾收集
#### 内存碎片化
由于CMS使用的是标记-清除算法,对存活对象没有进行地址的移动,所以回收对象之后就会产生内存碎片化(可用内存不连续),对于分配一些较大内存对象内存空间的时候就很尴尬,且内存的不连续也不能使用指针碰撞技术,只能使用空闲列表来进行内存的分配
#### 优缺点
* 优点:并发收集、低延迟、低停顿
* 缺点:
1.对CPU资源非常敏感:在并发阶段虽然不会造成STW的发生,但是会因为其垃圾回收线程占用的服务器资源导致程序变慢,总的吞吐量将会有一定的降低
2.无法处理浮动垃圾(Floating Garbage):在并发标记的阶段中,如果产生新的垃圾对象,CMS将无法对这些垃圾进行识别标记(从GC Roots直接关联对象出发遍历整个对象引用结构),就会导致这一部分的垃圾没有被及时的回收掉。只能在下一次执行GC的时候对这一部分垃圾进行处理
3.“标记-清除”算法会产生大量空间碎片,大对象无法存放发生后,不得不提前的触发Full GC
#### CMS"标记-清除"算法实现
1. 初始标记(CMS initial mark)
2. 并发标记(CMS concurrent mark)
3. 重新标记(CMS remark)
4. 并发清除(CMS concurrent sweep)
**说明:**初始标记、重新标记仍然需要Stop The World
#### 相关参数
* \-XX:+UseConcMarkSweepGC:手动指定使用CMS,开启CMS之后,会自动将ParNew打开,即-XX:+UseParNewGC,此时JVM垃圾回收将会是**ParNew(新生代)+CMS(老年代)+Serial Old(CMS的后备)**的组合。
* \-XX:+CMSInitiatingOccupanyFraction:设置堆内存使用率阈值,一旦达到该设置的阈值,CMS将会开启进行垃圾回收。
* JDK5默认值为68。即68%,JDK6以上默认值为92
* **如果内存增长的较慢,可以增大该阈值,降低CMS的触发频率,如果内存增长较快,要适当的减小该阈值,以免触发Serial Old串行垃圾回收器,减少Full GC的次数**。
* \-XX:+UseCMSCompactAtFullCollection:用于CMS在垃圾回收之后对内存碎片进行整理,这个过长将会存在STW。
* \-XX:+CMSFullGCsBeforeCompaction:设置在执行多少次FullGC后对内存空间进行压缩整理,和-XX:+UseCMSCompactAtFullCollection搭配使用。
* \-XX:ParallelCMSThreads:设置CMS的线程数量,CMS默认线程数量为(**ParallelGCThreads**\+ 3)/ 4。**ParallelGCThreads是年轻代并行收集器Parallel的线程数**
- 前言
- Write once, run anywhere
- 概述
- JAVA虚拟机
- JVM整体结构
- JVM架构模型
- JVM虚拟机分类
- HotSpot VM
- JRockit
- IBM-J9
- Azul/zing VM
- Taobao VM
- Dalvik VM
- Graal VM
- JAVA源码编译机制
- Javac编译器
- 分析和输入到符号表
- 注解处理
- 语义分析和生成class文件
- ECJ编译器
- 类执行机制
- 字节码解释执行
- 栈顶缓存
- 部分栈帧共享
- 编译执行
- 即时编译器
- C1 Compiler
- C2 Compiler
- Graal编译器
- C1与C2编译器
- AOT
- 编译优化
- 字符串优化
- 方法内联
- 逃逸分析
- 同步消除
- 标量替换
- 栈上分配
- 去虚拟化/逆优化
- 多层编译
- JVM编译策略
- OSR编译
- 冗余削除
- CodeCache
- 常量编译优化
- JVM运行时数据区
- 程序计数器
- JAVA虚拟机栈
- 栈帧
- 局部变量表
- 操作数栈
- 本地方法栈
- Java调用native方法
- JVM Stacks && Native Stacks
- 堆-Heap
- 方法区(Method Area)
- 运行时常量池
- 常量传播优化
- MetaSpace
- 直接内存
- StackOverflowError
- 递归方法
- OutOfMemoryError
- 本地内存溢出
- 执行引擎
- 运行时数据区关联关系
- jdk8内存结构
- JMM内存模型
- JAVA内存模型
- JMM八种操作指令
- 内存屏障
- 指令重排
- as-if-serial语义
- Happen-Before规则
- 数据依赖性
- 原子性、可见性与有序性
- 伪共享
- CPU三级缓存
- 缓存行
- MESI协议
- Java中的伪共享
- ConcurrentHashMap伪共享解决方案
- 虚拟机对象
- 对象创建原理
- 对象内存布局
- 对象头
- 实例数据
- 对象的访问定位
- 垃圾收集器与内存分配策略
- GC相关概念
- TLAB
- JVM GC工作原理
- 内存管理
- JAVA引用分类
- 死亡标记
- 回收方法区
- 三色标记算法
- 垃圾收集算法
- 标记-清除算法
- 标记-整理算法
- 复制算法
- 分代收集算法
- HotSpot算法实现
- STW
- 垃圾收集器
- 常见的垃圾收集器
- 垃圾收集器分类
- Serial收集器
- Serial Old收集器
- ParNew收集器
- Parallel Scavenge收集器
- Parallel Old收集器
- CMS收集器
- CMS完整收集过程
- Card Table
- G1收集器
- 分代收集
- 空间整合
- 可预测的停顿时间模型
- G1&CMS
- 主要参数说明
- G1适用场景
- Remembered Set
- G1垃圾回收的过程
- G1优化建议
- Shenandoah
- ZGC
- 垃圾收集器特点
- GC日志
- GC策略的评价指标
- jvm card table数据结构
- 对象生存轨迹
- 类文件结构
- 魔数
- 版本号
- 常量池
- 访问标志
- 父类索引
- 接口集合
- 字段集合
- 方法集合
- 属性集合
- 类加载机制与类的初始化
- Java代码执行流程
- 类加载过程
- 抽象类ClassLoader
- 常见类加载器
- BootstrapClassLoader
- 自定义类加载器
- 线程上下文类加载器
- 双亲委派模型
- Tomcat类加载机制
- ServiceLoader
- 类的初始化
- 常见的JVM类加载异常
- ClassNotFoundException
- NoClassDefFoundError
- LinkageError
- ClassCastException
- 虚拟机性能调优监控与故障处理工具
- CPU利用率高/飙升
- 排查及解决方案
- 上下文切换
- GC问题定位解决方案
- prommotion failed
- FullGC频繁
- youngGC
- 内存问题
- 内存溢出和内存泄漏
- 内存溢出
- 栈溢出
- 堆溢出
- 对外内存溢出
- 内存泄漏
- 磁盘问题
- 线上问题解决方案
- 不定期出现的接口耗时现象
- 线程池异常
- 死锁问题
- JVM调优
- jvm参考配置
- jvm-jstat
- jvm-jmap
- jvm-jstack
- jinfo
- jps
- 虚拟机的退出
- Shutdown Hook
- JVM指令
- 附录
- 常用JVM指令
- Class文件版本号
- Class文件格式
- 方法访问标识
- jvm常量池
- 类或接口的访问标识
- 描述符标识字符含义
- 字段访问标识
- Java程序与Docker容器环境
- 基准测试