### 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容器環境
- 基準測試