1. 程式人生 > >系統頻繁Full gc問題分析及解決辦法

系統頻繁Full gc問題分析及解決辦法

一、場景描述

上週開始系統在業務高峰期一直收到Full gc報警,監控顯示fgc頻繁,下圖是監控圖,左邊紅框是優化前效果,右邊是優化後,優化後fgc基本為0

監控 
二、原因查詢

1.檢視gc日誌,發現old區fgc後大小沒有變化,如下圖:

gclog
2.去線上dump記憶體看是什麼物件,用memory analyzer分析,Retained Size竟然有2.4G,全是sun.awt.SunToolkit這個物件,其實到這一步已經可以確定是什麼問題了,只是自己對系統不是很熟悉,導致定位具體的問題程式碼花了一些時間

ma

三、原因分析

系統中有一個呼叫頻繁的介面會呼叫下面這個方法,目的是獲取圖片的寬高資訊,但是Image這個物件用完不會自動釋放,需要手動呼叫 flush()方法;以前沒有呼叫這個方法,就導致一有請求就會有大物件進入old區,在業務高峰期old區一會就被打滿,所以一直進行fgc 
public static Image getImage(String path) { 
ImageIcon icon = new ImageIcon(path); 
Image img = icon.getImage(); 
return img; 
}

四、解決辦法

其實不管是用Image還是BufferedImage,讀取圖片的寬高不用把圖片全部載入到記憶體,在圖片的寬高資訊其實是儲存在檔案頭中的,只 要按不同的格式讀取檔案的頭資訊就可以拿到寬高資訊 
使用ImageReader程式碼如下

Iterator readers = ImageIO.getImageReadersByFormatName(StringUtil.getFileSuffix(filePath)); 
ImageReader reader = (ImageReader)readers.next(); 
iis = ImageIO.createImageInputStream(is); 
reader.setInput(iis, true); 
return Pair.of(reader.getWidth(0),reader.getHeight(0));