YGC過(guò)于頻繁問(wèn)題以及解決方案
頻繁的 Young GC(YGC)通常反映JVM年輕代內(nèi)存配置或?qū)ο蠓峙錂C(jī)制存在問(wèn)題,以下是針對(duì)性排查和優(yōu)化方案:
一、快速定位瓶頸
實(shí)時(shí)監(jiān)控指標(biāo)
# 每2秒采集GC數(shù)據(jù)(替換PID) jstat -gcutil <pid> 2000 # 關(guān)鍵指標(biāo)解讀: - YGCT: Young GC總耗時(shí) - YGC: Young GC次數(shù) - EU/S0/S1: Eden/Survivor區(qū)使用率
正常情況:?jiǎn)未蝁GC耗時(shí)應(yīng)<50ms,1分鐘內(nèi)YGC次數(shù)<5次
GC日志分析
啟動(dòng)參數(shù)追加:
-Xlog:gc*=debug:file=gc.log:time,uptime,level,tags:filecount=5,filesize=100m
使用 GCeasy 在線解析日志,重點(diǎn)關(guān)注:
- 對(duì)象晉升速率(Promotion Rate)
- 分配失敗觸發(fā)GC(Allocation Failure)
二、核心優(yōu)化策略
A. 內(nèi)存結(jié)構(gòu)調(diào)整
參數(shù) | 典型場(chǎng)景 | 計(jì)算公式 |
---|---|---|
-XX:NewRatio=3 | 老年代與年輕代比例 3:1 | NewSize=Heap/(NewRatio+1) |
-XX:SurvivorRatio=8 | Eden與單個(gè)Survivor區(qū)比例 8:1:1 | Eden = Young/(SurvivorRatio+2) |
動(dòng)態(tài)計(jì)算工具:
使用 JVM Heap Calculator 可視化調(diào)整
B. 分配速率優(yōu)化
1.對(duì)象池化
對(duì)頻繁創(chuàng)建的短生命周期對(duì)象(如DTO)采用對(duì)象池:
// 使用Apache Commons Pool GenericObjectPool<Request> pool = new GenericObjectPool<>(new BasePooledObjectFactory<>() { @Override public Request create() { return new Request(); } });
2.堆外內(nèi)存
對(duì)大型臨時(shí)數(shù)據(jù)使用DirectByteBuffer:
ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024); // 1MB off-heap
C. 收集器專(zhuān)項(xiàng)優(yōu)化
G1調(diào)優(yōu)(推薦JDK8+)
-XX:+UseG1GC -XX:MaxGCPauseMillis=200 # 目標(biāo)停頓時(shí)間 -XX:G1NewSizePercent=30 # 年輕代最小占比 -XX:G1MaxNewSizePercent=60 # 年輕代最大占比
ZGC低延遲方案(JDK15+)
-XX:+UseZGC -XX:ZAllocationSpikeTolerance=5.0
三、異常場(chǎng)景處理
案例1:過(guò)早提升(Premature Promotion)
現(xiàn)象:Survivor區(qū)頻繁溢出,對(duì)象過(guò)早進(jìn)入老年代
解決:
-XX:TargetSurvivorRatio=60 # 控制Survivor空間利用率 -XX:+NeverTenure # 禁止直接晉升(G1可用)
案例2:內(nèi)存泄漏
堆轉(zhuǎn)儲(chǔ)分析
jmap -dump:live,format=b,file=heap.bin <pid>
用MAT工具檢查Retained Heap
最大的對(duì)象
弱引用監(jiān)控
WeakReference<Object> ref = new WeakReference<>(largeObj); if (ref.get() == null) System.out.println("對(duì)象已被回收");
四、終極應(yīng)急方案
當(dāng)無(wú)法立即修改代碼時(shí),內(nèi)存急救措施:
# 臨時(shí)擴(kuò)容年輕代(不重啟JVM) jcmd <pid> VM.set_flag -XX:NewSize=512m jcmd <pid> VM.set_flag -XX:MaxNewSize=512m # 強(qiáng)制啟動(dòng)Full GC回收老年代(慎用) jcmd <pid> GC.run
優(yōu)化驗(yàn)證流程:
- 使用 JMH 做GC壓力測(cè)試
- 對(duì)比優(yōu)化前后
jstat
的YGC頻率下降比例 - 通過(guò)APM工具(Arthas)觀察業(yè)務(wù)TPS波動(dòng)
通過(guò)以上方法,通??蓪GC頻率降低50%-90%。若仍存在異常,需要結(jié)合具體業(yè)務(wù)代碼進(jìn)行內(nèi)存分配路徑分析。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
深入了解Spring中g(shù)etBean()的五種方式
在本文中,我們將詳細(xì)介紹從BeanFactory中獲取bean的多種方式。簡(jiǎn)單地說(shuō),正如方法的名稱(chēng)所表達(dá)的,getBean()負(fù)責(zé)從Spring?IOC容器中獲取bean實(shí)例,希望對(duì)大家有所幫助2023-02-02Java常用時(shí)間工具類(lèi)總結(jié)(珍藏版)
這篇文章主要為大家詳細(xì)介紹了Java中一些常用時(shí)間工具類(lèi)的使用示例代碼,文中的代碼簡(jiǎn)潔易懂,對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下2022-07-07SpringBoot+VUE實(shí)現(xiàn)數(shù)據(jù)表格的實(shí)戰(zhàn)
本文將使用VUE+SpringBoot+MybatisPlus,以前后端分離的形式來(lái)實(shí)現(xiàn)數(shù)據(jù)表格在前端的渲染,具有一定的參考價(jià)值,感興趣的可以了解一下2021-08-08詳解JAVA序列化及實(shí)際應(yīng)用場(chǎng)景分析
序列化就是將對(duì)象轉(zhuǎn)換為可以存儲(chǔ)或傳輸?shù)男问?以實(shí)現(xiàn)對(duì)象持久化存儲(chǔ)到磁盤(pán)中,或者在網(wǎng)絡(luò)中傳輸,這篇文章介紹JAVA序列化及實(shí)際應(yīng)用場(chǎng)景分析,感興趣的朋友跟隨小編一起看看吧2024-12-12Spring Cloud中FeignClient實(shí)現(xiàn)文件上傳功能
這篇文章主要為大家詳細(xì)介紹了Spring Cloud中FeignClient實(shí)現(xiàn)文件上傳功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04java如何用遞歸生成樹(shù)形結(jié)構(gòu)
作者分享了自己在使用腳本之家資源進(jìn)行編程時(shí)的經(jīng)驗(yàn),包括準(zhǔn)備實(shí)體對(duì)象、測(cè)試數(shù)據(jù)、構(gòu)造樹(shù)形結(jié)構(gòu)遞歸函數(shù)、測(cè)試以及輸出結(jié)果等步驟,作者希望這些經(jīng)驗(yàn)?zāi)軐?duì)大家有所幫助,并鼓勵(lì)大家支持腳本之家2025-03-03淺談Java中GuavaCache返回Null的注意事項(xiàng)
Guava在實(shí)際的Java后端項(xiàng)目中應(yīng)用的場(chǎng)景還是比較多的,比如限流,緩存,容器操作之類(lèi)的,本文主要介紹了GuavaCache返回Null的注意事項(xiàng),感興趣的可以了解一下2021-10-10java實(shí)現(xiàn)文件上傳的詳細(xì)步驟
文件上傳是用戶(hù)將本地文件通過(guò)Web頁(yè)面提交到服務(wù)器的過(guò)程,涉及客戶(hù)端、服務(wù)器端、上傳表單等組件,在SpringBoot中,通過(guò)MultipartFile接口處理上傳文件,并將其保存在服務(wù)器,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10