問題排查之JVM記憶體泄漏
1.問題描述,部署在客戶服務器上的資料網關專案,客戶開發反應,出現服務器記憶體占用很高的問題,懷疑是否為我們部署的專案導致?
開始排查:
一.[endif]登錄到客戶服務器,首先確認是否是我們應用占用的記憶體
- [endif]查看記憶體占用排行
ps aux | sort -k4,4nr | head -n 10
發現了我們應用行程id的身影
- [endif]查看資料網關實時記憶體占用
命令:jps, top - p pid查看實時記憶體分別看
VmPeak行程所使用的虛擬記憶體的峰值
VmSize行程當前使用的虛擬記憶體的大小
VmLck已經鎖住的物理記憶體的大小(鎖住的物理記憶體不能交換到硬碟)
VmHWM行程所使用的物理記憶體的峰值
VmRSS行程當前使用的物理記憶體的大小
-
[endif]我不相信,再用cat/proc/pid/status查看網關記憶體,確認是網關記憶體泄漏導致,
-
[endif]回去翻一下代碼,沒看出來泄露的地方
-
[endif]開始嘗試調整jvm引數,希望能通過jvm的調優消除(希望肯定是,渺茫的)
使用-XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError
調整-Xms,-Xmx,-Xmn等引數,測驗環境跑,
引數設定發生oom時生成dump
結果是:oom還是出現了(預期內的)
- [endif]拿下dump使用jdk中自帶的jvisualvm進行分析
Dump匯入,看其里面的日志及記憶體GC等,以及第一次出現oom時的GC報錯,反復看,
發現初次報錯中,找到一些似曾相識的類關鍵字面孔,大概猜想是程式的那一段那一句,
-
[endif]本地專案跑起來,使用jvisualvm連接本地jdk監控記憶體,GC情況,以及物件記憶體占用情況,同時帶著猜想代碼段出現問題,可能會出現的情況,看執行緒的生成,
-
[endif]最后,我發現jvisualvm出現有一個創建執行緒數達7000加,同一名稱,
-
[endif]猜想,因為我存在監控定時任務,對kafka資料補償補償,
每隔10秒鐘會執行一次檢查,檢查使用單執行緒池,
案例代碼

KafkaProducer produce =kafkaConf.createProduce();
ExecutorService newSingleThreadExecutor =new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS,
new LinkedBlockingDeque<>());
newSingleThreadExecutor.submit(new Runnable() {
@Override
public void run() {
int i =0;
/**
* 呼叫處理執行重發邏輯
*/省略,,,,,,,
10.出現問題的原因
也就是上面紅色的代碼,每次都獲取了一個新的kafkaProduce物件,在池中有使用,用完后關閉執行緒池

newSingleThreadExecutor.shutdown();
while (true) {
if (newSingleThreadExecutor.isTerminated()) {
if(logger.isInfoEnabled()){
logger.info(“定時重試推送Kafka完成!關閉執行緒池成功!…”);
}
break;
}
}
日志確實是顯示關閉了,但是不明白為什么jvisualvm還是里面顯示重復創建這個執行緒,
當然到這里肯定是確認了kafkaProduce物件導致的記憶體泄露,
- [endif]解決,將kafkaProduce物件獲取使用單例,每次獲取到的都是同一個物件就好,

public KafkaProducercreateProduce() {
Properties properties = getkafkaProduceConf();
if (kafkaProducer ==null) {
synchronized (this) {
if (kafkaProducer ==null) {
kafkaProducer =new KafkaProducer<>(properties);
}
}
}
return kafkaProducer;
}
圖片不好上傳,將就使用文字啦,作業之余,記錄自己平時的一些小毛病,以及問題排查的思路,記錄自己的經驗和不足之處,筆記中可能會有很多不足之處,歡迎各位留言指正討論,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/236571.html
標籤:java
上一篇:使用Java撰寫簡單的陽歷日歷
