工作中遇到了OOM問題需要排查,在此做一下分享,也做一下筆記
這裏模擬了工作中的OOM場景,實際代碼就不拿出來了,以下是我自己寫的代碼
定義一個無界隊列,頻繁往裏面加入元素,代碼如下,經測試,這是會產生OOM的
/**
* @author mengfh
*
* @version 2020-7-3上午9:15:52
*
* @description OOM排查與優化
*/
public class OptimizeOOM {
public static void main(String[] args) {
testQueue();
}
private static void testQueue() {
Queue<ArrayList<TestVO>> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < 10000; i++) {
ArrayList<TestVO> list = new ArrayList<>();
for (int j = 0; j < 1000; j++) {
list.add(new TestVO());
}
queue.add(list);
}
}
}
啓動debug,讓線程掛起,然後找到jdk/bin目錄下的jconsole.exe,可以看到我們寫的程序正在運行
jconsole.exe裏面有很多VM相關的東西,對於我們分析和學習還是有幫助的,具體如下,信息數量比較大
既然要OOM,那我們就分析爲什麼OOM,這裏配置一下VM參數,生成dump文件和文件地址
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:/jad/heapdump.hprof
要注意的是dump文件是比較大的,我本地隨便跑一下就接近1G ,而我的最大堆內存是768M
拿到了dump文件,那麼就可以去分析dump文件哪裏出問題了
可以通過jdk自帶的jhat來分析,也可以通過相關MAT來分析,如下是Eclipse Memory Analyzer 工具
使用的話需要一定的基礎,LZ一年工作經驗,勉強能行,現在在逐步加強,具體使用可以去MAT官網
另外,dump文件分析可以參考這篇文章https://blog.csdn.net/sheldon178/article/details/79543671
除了jhat,jconsole和MAT以外,還有很多JDK自帶的性能監控工具如:jps,jstack,jmap,jstat等等
它們都在jdk/bin目錄下,可以通過cmd運行
以下是理想的解決方案,思想是把無界隊列變成有界隊列,然後控制生產者生產的速度和消費者線程消費的速度
OOM的產生原因很多,優化方案也很多,工作上的優化方案就不拿出來了,保密性高,怕出事
路漫漫其修遠兮,吾將上下而求索
private static void testQueue() {
Queue<ArrayList<TestVO>> queue = new LinkedBlockingQueue<>(100);
for (int i = 0; i < 10000; i++) {
ArrayList<TestVO> list = new ArrayList<>();
for (int j = 0; j < 1000; j++) {
list.add(new TestVO());
}
queue.add(list);
//業務處理
//......
//這裏假裝是消費者線程在消費,當然還有很多方式,這是最簡單的一種
queue.remove();
}
}