提升JVM性能之CMS垃圾回收器的優化分析與案例剖析

這里寫目錄標題

      • 一、CMS基本介紹
      • 二、CMS核心優化策略
        • 1. 避免并發模式失敗(Concurrent Mode Failure)
        • 2. 減少內存碎片
        • 3. 調優并發階段耗時
        • 4. 新生代優化配合
      • 三、典型案例解析
        • 案例1:電商服務頻繁Full GC
        • 案例2:金融交易系統碎片導致長時間停頓
      • 四、關鍵參數清單
      • 五、升級替代方案
      • 六、調優流程

優化CMS垃圾回收器(Concurrent Mark-Sweep)是提升JVM性能的關鍵手段,尤其適用于追求低延遲的老年代回收場景。以下結合核心優化策略與真實案例,為你提供系統化的解決方案:


一、CMS基本介紹

核心目標: CMS 垃圾回收器的主要設計目標是 最小化垃圾回收導致的應用程序停頓時間(Stop-The-World, STW)。它特別適用于那些對響應時間敏感的應用程序,例如 Web 服務器、GUI 桌面應用、API 服務等。

核心特點: 并發標記和清除

CMS 的核心在于它的大部分工作(標記和清除階段)是與用戶線程并發執行的,大大減少了 STW 的時間。這也是它被稱為“并發”收集器的原因。

工作流程(四個主要階段):

  1. 初始標記(Initial Mark - STW):

    • 這是第一個短暫的 STW 階段。
    • 目標:快速標記所有直接從 GC Roots(如線程棧變量、靜態變量、JNI 引用等)直接可達的存活對象
    • 為什么快?因為它只標記直接關聯的對象,不進行深度掃描。
    • 停頓時間通常很短。
  2. 并發標記(Concurrent Mark):

    • 最重要的并發階段。
    • 目標:沿著初始標記階段標記出的存活對象圖,深度遍歷整個老年代對象圖,標記所有可達的(存活的)對象。
    • 關鍵點: 這個階段與用戶線程并發執行。用戶線程仍在運行,可能會修改對象的引用關系(導致新對象產生或舊對象不可達)。
    • 因為并發,此階段耗時較長,但不會暫停應用。
  3. 重新標記(Remark - STW):

    • 第二個(通常也是較長的)STW 階段。
    • 目標:修正在并發標記階段,由于用戶線程繼續運行而導致發生變化的引用關系(即標記那些在并發標記過程中新產生的垃圾或新晉升為存活的對象)。CMS 使用了一些技術(如增量更新或原始快照)來高效地完成這個修正工作。
    • 雖然需要 STW,但 CMS 通過各種優化手段(如預清理、卡表)盡量縮短這個階段的時間。
    • 停頓時間比初始標記長,但遠小于并發標記的總時間(因為并發標記不暫停)。
  4. 并發清除(Concurrent Sweep):

    • 第三個并發階段。
    • 目標:回收在標記階段被確定為不可達(垃圾)的對象所占用的內存空間
    • 關鍵點: 這個階段與用戶線程并發執行。用戶線程可以繼續分配新對象。
    • 回收后的內存空間不會立即進行壓縮整理,因此是空閑列表(Free List)管理。

關鍵優勢和適用場景:

  • 低延遲/短停頓: 最大的優勢!通過并發執行大部分耗時的標記和清除工作,顯著減少了 STW 的總時間,使得應用程序響應更流暢。
  • 適合交互式應用: 對用戶交互響應時間要求高的場景(如 GUI 程序、Web 請求響應)。
  • 老年代收集器: CMS 主要用來回收老年代的對象。它通常需要與一個負責新生代回收的收集器(最常見的是 ParNew)配合使用。

主要缺點和挑戰:

  1. CPU 資源敏感:

    • 在并發標記和并發清除階段,垃圾回收線程會與用戶線程競爭 CPU 資源。如果 CPU 資源緊張,可能導致應用程序吞吐量下降。
    • 默認的回收線程數 = (CPU 核心數 + 3)/4。在 CPU 核心數少的情況下,并發回收線程可能占用過多 CPU。
  2. 無法處理“浮動垃圾”(Floating Garbage):

    • 在并發標記階段,用戶線程還在運行,可能產生新的垃圾對象(標記階段結束后才成為垃圾)或使一些已標記的對象變為垃圾。
    • 這些垃圾(浮動垃圾)無法在當前回收周期被清除,只能留到下一次 GC。
    • 這可能導致需要預留更多空間(-XX:CMSInitiatingOccupancyFraction 參數設置觸發閾值,如 70%),以防在回收完成前老年代就滿了。
  3. “并發模式失敗”(Concurrent Mode Failure):

    • 最嚴重的問題! 如果在 CMS 執行過程中(特別是并發階段),老年代空間不足以容納從新生代晉升上來的對象或者新分配的大對象,JVM 就會被迫中斷 CMS 的并發回收過程。
    • 此時,JVM 會觸發一次 Serial Old(單線程)Full GC。這是一個非常耗時的 STW 過程,會暫停所有用戶線程,并對整個堆(包括新生代和老年代)進行標記-清除-壓縮。這與使用 CMS 的初衷(低延遲)背道而馳。
    • 觸發原因通常是:老年代空間預留不足(觸發閾值設置過高)、晉升過快、大對象過多、內存碎片嚴重導致無法分配連續空間。
  4. 內存碎片(Memory Fragmentation):

    • CMS 采用的是 標記-清除(Mark-Sweep)算法,而不是標記-整理(Mark-Compact)。它只清除垃圾對象,不移動存活對象進行內存壓縮
    • 經過多次回收后,老年代會產生大量不連續的內存碎片。當需要分配一個較大連續內存空間的對象時,即使總的剩余空間足夠,也可能因為找不到足夠大的連續空間而觸發 Full GC(通常是 Serial Old) 來進行壓縮整理。
    • 為了緩解碎片,CMS 提供了 -XX:+UseCMSCompactAtFullCollection(在 Full GC 時壓縮,默認開啟)和 -XX:CMSFullGCsBeforeCompaction(執行多少次不壓縮的 Full GC 后,再執行一次帶壓縮的 Full GC,默認為 0,表示每次進入 Full GC 都壓縮)參數,但這又會帶來更長的 STW 時間。
  5. 對新生代回收器的依賴: CMS 本身不管理新生代,必須配合一個新生代收集器(如 ParNew、Serial)。如果新生代 GC 頻繁或耗時長,也會間接影響整體停頓時間。

二、CMS核心優化策略

1. 避免并發模式失敗(Concurrent Mode Failure)
  • 問題本質:CMS并發清理時,老年代空間不足以容納新晉升對象,觸發Full GC(Stop-The-World)。
  • 優化方案
    • 增大老年代空間(-XX:NewRatio 調整新生代/老年代比例)
    • 降低對象晉升速度:
      -XX:MaxTenuringThreshold=6      # 提高對象在新生代存活次數
      -XX:+UseCMSInitiatingOccupancyOnly
      -XX:CMSInitiatingOccupancyFraction=70  # 老年代70%時啟動CMS
      
2. 減少內存碎片
  • 啟用壓縮
    -XX:+UseCMSCompactAtFullCollection   # Full GC后壓縮內存
    -XX:CMSFullGCsBeforeCompaction=2     # 每2次Full GC壓縮一次
    
3. 調優并發階段耗時
  • 縮短初始標記(STW階段)
    -XX:+CMSParallelInitialMarkEnabled  # 并行初始標記
    
  • 并發標記/清理線程數
    -XX:ConcGCThreads=4  # 推薦為CPU核數的1/4
    
4. 新生代優化配合
  • 選擇合適的新生代回收器
    -XX:+UseParNewGC  # CMS默認搭配ParNew
    
  • 調整Eden/Survivor
    -XX:SurvivorRatio=8  # Eden與Survivor比例
    

三、典型案例解析

案例1:電商服務頻繁Full GC
  • 現象:高峰期每10分鐘發生Concurrent Mode Failure,停頓2秒。
  • 原因分析
    • 老年代大小固定為2GB,CMSInitiatingOccupancyFraction=68
    • 日志顯示并發階段未完成時老年代已滿
  • 優化措施
    -XX:CMSInitiatingOccupancyFraction=60  # 更早啟動CMS
    -XX:NewRatio=3                         # 老年代從2GB→3GB
    -XX:MaxTenuringThreshold=8             # 減少短期對象晉升
    
  • 結果:Full GC消失,平均延遲下降65%
案例2:金融交易系統碎片導致長時間停頓
  • 現象:每日凌晨Full GC耗時8秒,影響結算流程。
  • 原因分析
    • CMSFullGCsBeforeCompaction=0(默認每次Full GC都壓縮)
    • 內存碎片率達40%
  • 優化措施
    -XX:CMSFullGCsBeforeCompaction=4     # 減少壓縮頻率
    -XX:+UseCMSInitiatingOccupancyOnly
    -XX:CMSInitiatingOccupancyFraction=50 # 預留更多空間防失敗
    
  • 結果:Full GC時間降至1.5秒,碎片率<15%

四、關鍵參數清單

參數建議值作用
-XX:+UseConcMarkSweepGC必啟用啟用CMS
-XX:CMSInitiatingOccupancyFraction60-75老年代觸發回收閾值
-XX:+UseCMSInitiatingOccupancyOnly必啟用避免JVM動態調整閾值
-XX:ConcGCThreadsCPU核數/4并發線程數
-XX:+CMSScavengeBeforeRemark推薦啟用重新標記前Young GC

五、升級替代方案

若優化后仍不滿足需求(如堆>8GB或停頓>200ms),考慮遷移至:

  1. G1垃圾回收器
    -XX:+UseG1GC -XX:MaxGCPauseMillis=200
    
  2. ZGC(JDK11+):
    -XX:+UseZGC -Xmx16g  # 亞毫秒級停頓
    

六、調優流程

  1. 監控診斷
    -Xlog:gc*:file=gc.log  # JDK9+統一日志
    jstat -gcutil <pid> 1000
    
  2. 分析工具
    • GCViewer 分析日志
    • Eclipse Memory Analyzer 排查內存泄露
  3. 壓測驗證
    jmeter -n -t test.jmx # 模擬流量驗證優化效果
    

關鍵建議:CMS優化需結合對象生命周期分析(JProfiler)與壓力測試,避免僅憑經驗調整。對于新項目,優先選擇G1或ZGC以規避CMS碎片問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/91775.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/91775.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/91775.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Token系列 - 再談穩定幣

相關政策 2024年12月&#xff0c;歐洲《加密資產市場監管法案》正式成為法律2025年3月&#xff0c;日本細化了加密資產及穩定幣的監管調整2025年5月&#xff0c;英國發布了關于穩定幣發行、加密資產托管及加密資產公司財務穩健性的監管提案&#xff1b;2025年5月20日&#xff…

【20min 急速入門】使用Demucs進行音軌分離

創建環境 conda create --name mujica python3.10下載加速依賴 先用nvidia-smi檢查機器使用的獨顯版本, 然后從pytorch官網下載對應的GPU版torch, torchaudio 比如我的是12.2, 就下載11.8版本的 pip3 install torch torchvision torchaudio --index-url https://download.p…

字節Seed發布擴散語言模型,推理速度達2146 tokens/s,比同規模自回歸快5.4倍

用擴散模型寫代碼&#xff0c;不僅像開了倍速&#xff0c;改起來還特別靈活&#xff01;字節Seed最新發布擴散語言模型Seed Diffusion Preview&#xff0c;這款模型主要聚焦于代碼生成領域&#xff0c;它的特別之處在于采用了離散狀態擴散技術&#xff0c;在推理速度上表現出色…

海洋大地測量基準與水下導航系列之九我國海洋PNT最新技術進展(下)

三、海洋PNT技術裝備研發與工程化應用 1.海底基準裝備 研制了首批適應海洋環境的多型海底基準站裝備&#xff0c;在我國南海海域成功布設了定位精度優于0.25m的海底大地測量試驗基準網&#xff0c;實現了我國海底大地測量基準技術零的突破。基準方艙具備穩固、抗壓、防腐、防…

入門MicroPython+ESP32:安裝逗腦IDE及驅動

本篇文章將手把手帶大家入門MicroPython ESP32&#xff0c;重點介紹逗腦IDE的安裝過程以及相關驅動的安裝。 一、下載逗腦IDE 要開始使用逗腦IDE&#xff0c;首先需要從官網下載最新版本。請訪問以下網址進行下載&#xff1a;https://www.itprojects.cn/ide 下載時的界面大…

CentOS上部署Redis及其哨兵(Sentinel)模式

架構&#xff1a;說明我這里是偽集群的&#xff0c;redis 在同一臺機器&#xff0c;Sentinel 只有一個&#xff0c;也存在單點故障問題只能當作開發環境使用&#xff0c;要滿足生產至少是下面這種架構 ------------------- ------------------- ------------------- …

《軟件測試與質量控制》實驗報告二 單元測試

目 錄 一、實驗學時 二、實驗目的 三、實驗環境 &#xff08;一&#xff09;硬件環境&#xff1a; &#xff08;二&#xff09;軟件環境&#xff1a; 四、實驗內容 1、實驗方案&#xff1a; 2、實驗步驟&#xff1a; 3、設計思路&#xff1a; 1、安裝JUnit和Eclemma…

k8s模式部署PolarDB-X

當前文檔適配PolarDB-X V2.4.0 版本 環境描述&#xff1a; 部署機&#xff08;ops&#xff09;1x2.2x.2x8.116&#xff0c;部署機需要可以訪問互聯網。使用ansible進行部署&#xff0c;自行安裝ansible。需要部署兩個k8s集群&#xff0c;分別在其上安裝一個polardb-x集群。 部…

Flask + YARA-Python*實現文件掃描功能

以下是一個 完整的 Web API 示例&#xff0c;使用 Flask YARA-Python 實現文件掃描功能&#xff0c;支持上傳文件并返回 YARA 規則匹配結果。 ? 功能說明 提供一個 /scan 接口&#xff0c;支持文件上傳使用預加載的 YARA 規則進行掃描返回 JSON 格式的匹配結果支持多規則、可…

WinForm之NumericUpDown控件

NumericUpDown&#xff08;數字上下控件&#xff09;是 WinForm 中專門用于輸入和調整數值的控件&#xff0c;它結合了文本框和上下按鈕&#xff0c;用戶可通過點擊按鈕或直接輸入來設置數值&#xff0c;且能嚴格限制數值范圍&#xff08;最小值、最大值&#xff09;和步長&…

一文讀懂K8S kubectl 命令,運維小白必看!

一、Kubectl 是什么? Kubectl 是 Kubernetes(簡稱 K8S)集群的命令行工具,它就像是一把萬能鑰匙,讓我們可以與 K8S 集群進行交互,輕松管理集群中的各種資源,像是 Pod、Service、Deployment 等等。通過向 K8S API 發送 REST 請求,kubectl 實現了對集群資源的增刪改查等操…

髖臼方向的定義與測量-I

近期看到關于髖臼方向不同應用場景下的不同定義&#xff0c;覺得特別有意思&#xff0c;但是&#xff0c;原文是影印本&#xff0c;不太方便實用屏幕取詞翻譯&#xff0c;且一些專業術語也不太好理解。 因此&#xff0c;我將原文和翻譯整理了一些&#xff0c;不對的地方&#x…

Python爬蟲實戰:研究mahotas庫,構建圖像獲取及處理系統

一、引言 (一)研究背景 在信息爆炸的時代,圖像作為一種直觀、豐富的信息載體,其數量在互聯網上呈現指數級增長。這些圖像數據涵蓋了自然景觀、動植物、工業產品等多個領域,為模式識別、機器學習等研究提供了寶貴的數據源。特別是在植物學研究領域,葉片圖像包含了豐富的…

【04】海康相機C#開發——VS 在編譯時,提示“Files的值“+亂碼情況解決辦法’ ,C#項目打開編譯時報錯:Files 的值“IGEF‘,

文章目錄C#項目打開&#xff0c;用VS 在編譯時編譯時報錯&#xff1a;Files 的值“亂碼&#xff1b; 有的編譯器會顯示&#xff1a;Files的值“IGEF 以上報錯都為同一種錯誤&#xff0c;.net中的配置文件亂碼導致的&#xff1a; 找到項目目錄下的“..\obj\Debug\”的文件夾中…

MySQL隱式轉換陷阱:從錯誤查詢案例解析索引失效與數據類型匹配

開始之前&#xff0c;先問個問題問題&#xff1a;mysql 數據類型是date &#xff0c;怎么寫查詢條件索引有效&#xff1f; ——下面帶著疑問看下去。 一、mysql-8.隱式轉換導致索引失效或查出不符合where條件結果 今天在執行一條sql語句時候&#xff0c;where條件寫錯了&#x…

【sklearn(01)】數據集加載、劃分,csv文件創建,特征工程,無量綱化

目錄sklearn數據集玩具數據集現實世界數據集加載玩具數據集獲取現實世界數據集本地csv數據創建csv文件pandas加載csv數據集劃分特征工程步驟特征工程APIDictVectorizer 字典列表特征提取APICountVectorizer 文本特征提取API英文文本提取中文文本提取TfidfVectorizer TF-IDF文本…

docker desktop入門(docker桌面版)(提示wsl版本太低解決辦法)

參考文章&#xff1a;Docker Desktop Engine Stopped原因分析&#xff08;docker桌面停止&#xff09;WSL沒裝或沒更新 文章目錄Docker Desktop入門指南1. Docker Desktop簡介2. 安裝Docker Desktop2.1 系統要求2.2 下載和安裝3. 配置Docker Desktop修改默認存儲路徑4. 運行你的…

《n8n基礎教學》第三節:模擬一個自動化場景

1、模擬場景Nathan &#x1f64b;是 ABCorp 的分析經理&#xff0c;他的工作是支持 ABCorp 團隊的報告和分析。作為一個真正的多面手&#xff0c;他還負責處理一些雜項任務。Nathan 做的一些事情是重復且枯燥的。他希望自動化其中一些任務&#xff0c;以避免精疲力竭。作為一名…

CodeRush AI 助手進駐 Visual Studio:AiGen/AiFind 亮相(三)

CodeRush 是專為 Visual Studio 打造的高效開發插件&#xff0c;通過集成 AI 驅動功能&#xff08;如自然語言生成代碼的 AiGen 和智能搜索邏輯的 AiFind&#xff09;、語音交互及深度重構工具&#xff0c;直接在 IDE 內無縫完成代碼生成、修改與導航&#xff0c;消除窗口切換與…

如何從頭開始搭建屬于自己的家用nas實現內網穿透訪問

最近我在家部署了群暉NAS923&#xff0c;從而實現內網穿透&#xff0c;下面寫一個新手向教程&#xff1a; 一、硬件安裝與初始化設置 1. 硬盤安裝&#xff08;已完成可跳過&#xff09; 群暉 923 支持 4 塊 3.5 英寸硬盤&#xff0c;開箱后取出硬盤架&#xff0c;將硬盤&am…