JVM GC長暫停問題排查
現象
名詞:GC 垃圾回收(Garbage Collection)分類 計算機科學
在高并發下,Java程序的GC問題屬于很典型的一類問題,帶來的影響往往會被進一步放大。不管是「GC頻率過快」還是「GC耗時太長」,由于GC期間都存在Stop The World問題,因此很容易導致服務超時,引發性能問題。
事情最初是線上某應用垃圾收集出現Full GC異常的現象,應用中個別實例Full GC時間特別長,持續時間約為15~30秒,平均每2周左右觸發一次;
JVM參數配置“-Xms2048M –Xmx2048M –Xmn1024M –XX:MaxPermSize=512M”
-
周期性長暫停
- 線上Java應用每2周觸發1次Full GC
- 單次暫停15-30秒(正常Full GC應≤1秒)
- 僅部分實例出現,JVM配置一致(
-Xms2048M –Xmx2048M –Xmn1024M –XX:MaxPermSize=512M
)
-
異常GC特征
- Full GC原因標記為
Ergonomics
(JVM自適應策略觸發) - GC日志未顯示堆內存異常(回收前后內存占比正常)
- Full GC原因標記為
背景
-
系統環境
- 部署于 Linux虛擬機(物理內存8GB)
- 關鍵參數:
vm.swappiness=30
(默認傾向使用SWAP)
-
并發場景
- 高QPS服務:持續內存分配壓力
- 內存使用特點:
監控項 現象 物理內存 未完全耗盡( free
顯示可用內存充足)SWAP分區 占用305MB(進程檢測) CPU Full GC時驟增
-
矛盾點
- JVM認為內存充足(堆配置僅2GB),但OS將部分內存頁換出到SWAP磁盤
- 低頻率Full GC(2周1次)→ 內存頁在SWAP停留時間長 → GC遍歷時觸發磁盤換入
核心沖突示意圖
JVM Full GC
│
├─ 需遍歷堆內存
│ │
│ ├─ 內存頁在物理內存 → 微秒級訪問
│ │
│ └─ 內存頁在SWAP磁盤 → 毫秒級磁盤I/O(**10^3倍延遲**)
│
└─ 大量頁換入操作阻塞GC線程 → **STW時間膨脹至秒級**
關鍵結論:低頻Full GC + SWAP換出 + 遍歷換入需求 = 長暫停災難鏈
第一層:核心概念定義
-
JVM與GC機制
- Java虛擬機(JVM)通過垃圾回收(GC)管理內存,GC執行時會觸發"Stop The World"(STW)暫停
- Full GC:清理整個堆內存的回收操作,耗時顯著
-
問題現象
- 某應用實例周期性出現15-30秒Full GC
- JVM配置:
-Xms2048M –Xmx2048M –Xmn1024M –XX:MaxPermSize=512M
- Full GC誘因:Ergonomics(自適應策略觸發)
第二層:系統級分析
-
GC日志與服務器指標關聯
- GC日志顯示回收前后堆內存無異常
- 監控發現Full GC時點出現:
- CPU使用率驟增(圖1紅框)
- 物理內存增長拐點 + SWAP區釋放(圖1橙框)
-
SWAP機制驗證
# 檢測進程SWAP占用 for i in $(cd /proc; ls | grep "^[0-9]" | awk '$0>100'); do awk '/Swap/{a=a+$2} END{print '"$i"',a/1024"M"}' /proc/$i/smaps 2>/dev/null done | sort -k2nr | head -10
- 目標進程占用SWAP 305MB
- 異常實例swappiness=30(傾向使用SWAP),正常實例swappiness=0
第三層:根因分析
-
SWAP與GC的致命交互
- Linux內存壓力時:物理內存頁換出到SWAP(swap out)
- Full GC遍歷堆內存時:SWAP數據換回物理內存(swap in)
- 磁盤I/O操作導致GC遍歷耗時劇增(從毫秒級→秒級)
-
對比實驗佐證
場景 SWAP用量 Full GC耗時 關鍵差異 問題實例(2周1次) 305MB 15-30秒 內存頁被換出至SWAP 實名服務(幾小時1次) 54MB 576ms SWAP無活動+頻繁GC避免換出
第四層:解決方案
-
臨時措施
sysctl vm.swappiness=0 # 禁用SWAP傾向 swapoff -a # 關閉SWAP分區(需確保物理內存≥SWAP用量)
-
永久配置
vm.swappiness=0
-
效果驗證
- 關閉SWAP后Full GC耗時降至190ms(圖2橙框)
基座:延伸思考
-
關鍵疑問解答
- Q:SWAP是否必然導致GC卡頓?
A:否!僅當GC時發生swap in操作才會引發(實名服務證明) - Q:JVM為何不禁用SWAP?
A:Linux內存管理需平衡安全性與性能(kswapd守護進程機制)
- Q:SWAP是否必然導致GC卡頓?
-
最佳實踐
- 高并發服務建議:
vm.swappiness=0
+ 足夠物理內存 - 備選方案:降低堆大小(避免內存換出)
- 高并發服務建議:
-
核心結論復述
SWAP與GC同時觸發→內存頁換入換出→磁盤I/O阻塞STW→秒級卡頓,通過禁用SWAP或優化內存配置可根治。
原文參考https://blog.csdn.net/cnzzs/article/details/141273193