Java線上頻繁FullGC的完整排查流程
一、先明確:FullGC觸發(fā)常見原因
- 老年代空間不足、內(nèi)存泄漏/內(nèi)存溢出
- 大對象直接進老年代、頻繁晉升
- MetaSpace元空間滿、動態(tài)加載類過多
- System.gc()代碼主動調(diào)用、RMI定時FullGC
- JVM參數(shù)不合理:新生代太小、Survivor過小、晉升閾值異常
- 堆內(nèi)存分配過小、物理內(nèi)存被其他進程搶占
核心排查思路:先抓現(xiàn)場 → 看GC日志定位類型 → 堆快照分析 → 代碼定位 → 壓測復(fù)現(xiàn) → 調(diào)參優(yōu)化
二、階段1:緊急應(yīng)急(線上不能停服優(yōu)先)
1. 基礎(chǔ)信息采集
# 查看java進程PID jps -l # 實時看GC狀態(tài) jstat -gcutil PID 1000
重點指標:
- O(老年代使用率)持續(xù)上漲 → 內(nèi)存泄漏/對象不停晉升到老年代
- M(元空間)持續(xù)漲滿 → 類加載泄漏
- S0/S1長期幾乎滿、Eden快速打滿 → 新生代過小,對象頻繁提前晉升老年代
2. 臨時規(guī)避(業(yè)務(wù)優(yōu)先??捎茫?/h3>
- 臨時擴容-Xmx/-Xms,增大堆,緩解頻繁FGC
- 臨時關(guān)閉RMI自動FullGC:
-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 - 臨時下線可疑定時任務(wù)、批量導(dǎo)入、大文件解析接口
-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000三、階段2:采集GC日志,定位FGC根因分類
1. 開啟/導(dǎo)出GC日志(沒提前配置則動態(tài)抓?。?/h3>
JVM啟動參數(shù)必備(生產(chǎn)標配):
-Xloggc:/xxx/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC
根據(jù)GC日志區(qū)分4大類FGC:
- 老年代占滿觸發(fā)FGC(最常見)
日志關(guān)鍵字:Allocation Failure,Eden耗盡→對象晉升老年代,老年代不足觸發(fā)FullGC - MetaSpace滿觸發(fā)FGC
日志:Metaspace allocation failure,動態(tài)代理、熱加載、頻繁創(chuàng)建ClassLoader - System.gc()主動觸發(fā)
日志:Full GC (System.gc()),代碼/第三方包顯式調(diào)用System.gc() - CMS并發(fā)失敗/晉升擔保失敗(CMS收集器)
concurrent mode failure / promotion failed:老年代預(yù)留空間不足,擔保失敗觸發(fā)STW FullGC
四、階段3:dump堆快照,定位占用內(nèi)存的對象(核心步驟)
抓堆時機:FGC頻繁、老年代占用率80%+還沒OOM時dump,避免OOM后數(shù)據(jù)丟失
方式1:命令行dump
jmap -dump:format=b,file=heap.hprof PID # 生產(chǎn)dump建議加參數(shù),不阻塞業(yè)務(wù): jmap -dump:live,format=b,file=heap.hprof PID
方式2:OOM自動dump(提前配置)
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/xxx/heap.hprof
堆文件分析工具
- MAT(Eclipse Memory Analyzer,首選)
- Leak Suspects:泄漏可疑報告(一鍵定位泄漏對象)
- Dominator Tree:支配樹,查看占用堆最多的對象
- Histogram:按類統(tǒng)計實例數(shù)量、占用內(nèi)存
- JProfiler、Arthas在線分析(不用下載大hprof)
五、階段4:Arthas在線實時排查(不用重啟、不用dump大文件)
1. 安裝啟動Arthas
curl -O https://arthas.aliyun.com/arthas-boot.jar java -jar arthas-boot.jar
常用排查命令
# 1. 實時監(jiān)控GC gc -i 1000 # 2. 查看堆內(nèi)存實時分布 heapdump --live /tmp/dump.hprof # 3. 查看對象實例數(shù)量,快速找暴漲對象 dashboard # 4. 追蹤創(chuàng)建大量對象的方法 trace 全類名 方法名 # 5. 排查ClassLoader泄漏 classloader
六、階段5:按場景逐個定位代碼問題
場景1:內(nèi)存泄漏(老年代緩慢漲,每次FGC回收不掉多少內(nèi)存)
常見泄漏點:
- 靜態(tài)集合(static List/Map)無限add對象,無移除邏輯
- ThreadLocal使用完未remove,線程池復(fù)用線程導(dǎo)致對象常駐
- 連接池、緩存(本地Cache)無過期淘汰,數(shù)據(jù)只增不減
- 第三方框架:Mybatis攔截器、定時任務(wù)、異步線程未銷毀對象
MAT定位:支配樹找到超大對象 → 查看引用鏈Reference Chain → 找到業(yè)務(wù)代碼
場景2:大對象頻繁創(chuàng)建直接進老年代
- 一次性讀取超大文件、全表查數(shù)據(jù)庫不分頁返回全量List
- 超大字符串拼接、一次性創(chuàng)建超大數(shù)組
JVM參數(shù):-XX:PretenureSizeThreshold=2M超過閾值直接進老年代,頻繁創(chuàng)建觸發(fā)FGC
場景3:元空間滿FGC
- 動態(tài)生成代理類(CGLIB頻繁創(chuàng)建)、Groovy腳本熱加載
- 自定義ClassLoader不停新建不卸載,
-XX:MaxMetaspaceSize配置過小
場景4:代碼主動System.gc()
- 第三方SDK、老版本RPC、定時任務(wù)里隱式調(diào)用System.gc()
- 代碼檢索
System.gc()全局關(guān)鍵字,使用Arthaswatch攔截調(diào)用
七、階段6:JVM參數(shù)優(yōu)化(分收集器:G1/CMS/ZGC)
通用優(yōu)化方向
- 新生代大?。篍den占堆1/3~1/2,避免Eden過小頻繁晉升
- 調(diào)整SurvivorRatio、MaxTenuringThreshold晉升年齡,減少過早晉升到老年代
- 禁用顯式GC:
-XX:+DisableExplicitGC(謹慎:NIO依賴System.gc堆外內(nèi)存則不能加) - 合理設(shè)置MetaSpace:
-XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M
G1收集器(主流生產(chǎn))
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 # 預(yù)期STW停頓 -XX:G1HeapRegionSize=16M
CMS老項目優(yōu)化
- 調(diào)高老年代預(yù)留空間:
-XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly,避免并發(fā)失敗FullGC
八、階段7:復(fù)現(xiàn)驗證+上線落地優(yōu)化
- 本地/測試環(huán)境壓測(JMeter)復(fù)現(xiàn)FGC,修復(fù)代碼后壓測驗證GC平穩(wěn)
- 上線灰度發(fā)布,上線后持續(xù)監(jiān)控GC指標(Prometheus+Grafana)
- 告警配置:老年代使用率>80%、10min內(nèi)FullGC>3次觸發(fā)告警
九、排查速記口訣
先jstat看GC趨勢 → 拉GC日志分FGC類型 → arthas在線查對象 → dump堆MAT找泄漏引用 → 改代碼+調(diào)JVM參數(shù) → 壓測驗證上線
到此這篇關(guān)于Java線上頻繁FullGC的完整排查流程的文章就介紹到這了,更多相關(guān)Java線上頻繁FullGC內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
分頁技術(shù)原理與實現(xiàn)之Java+Oracle代碼實現(xiàn)分頁(二)
這篇文章主要介紹了分頁技術(shù)原理與實現(xiàn)的第二篇:Java+Oracle代碼實現(xiàn)分頁,感興趣的小伙伴們可以參考一下2016-06-06
Java泛型機制與反射原理相關(guān)知識總結(jié)
今天帶大家學(xué)習的是關(guān)于Java進階的相關(guān)知識,文章圍繞著Java泛型機制與反射原理展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下2021-06-06
SpringBoot項目Jar包使用systemctl運行過程
這篇文章主要介紹了SpringBoot項目Jar包使用systemctl運行過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-03-03
Spring WebFlux實現(xiàn)參數(shù)校驗的示例代碼
請求參數(shù)校驗,在實際的應(yīng)用中很常見,網(wǎng)上的文章大部分提供的使用注解的方式做參數(shù)校驗。本文主要介紹 Spring Webflux Function Endpoint 使用 Spring Validation 來校驗請求的參數(shù)。感興趣的可以了解一下2021-08-08
eclipse自動創(chuàng)建SpringBoot項目報錯的解決
這篇文章主要介紹了eclipse自動創(chuàng)建SpringBoot項目報錯的解決方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01

