頻繁FullGC的問題排查和解決
阿新 • • 發佈:2018-12-29
一、問題排查
1.jstat -gc 【pid】檢視gc情況
2.發現FullGC過多,通過 jmap -histo 【pid】檢視堆中物件統計
二、問題解決
實際工作中,主要發現兩個資料結構相關原因會導致FULL GC
1. LinkedBlockingQueue$Node
當資料量很大時,LinkedBlockingQueue會無限制存放資料,最終導致Allocation Failure的Full GC。由下圖可知LinkedBlockingQueue的無參建構函式是一個無界佇列,所以需要使用有參建構函式併合理設定數值來限制節點數量。
。
2.執行緒池
使用Executors.newFixedThreadPool(nThreads)構造執行緒池處理訊息,結果由於訊息量很大,造成記憶體消耗過快,頻繁FULL GC,其本質原因也是佇列無限存放資料。
解決方案是構造一個阻塞的容量5000的任務佇列,且在佇列滿的時候執行CalllerRunsPolicy的拒絕策略
new ThreadPoolExecutor(nThreads, nThreads, 30, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5000), new ThreadPoolExecutor.CallerRunsPolicy());