jvm記憶體溢出問題的定位方法
- 2019 年 10 月 3 日
- 筆記
jvm記憶體溢出問題的定位方法
今天給大家帶來JVM體驗之記憶體溢出問題的定位方法。
廢話不多說直接開始:
一、Java堆溢出
測試程式碼如下:
import java.util.*; public class A { public static void main(String[] args) { List<String> strList = new ArrayList<>(); while(true) { strList.add(""); } } }
運行過程如下所示:
我們在這裡可以看到記憶體在不斷的上漲,而Java在到一定時候會爆出OOM異常。
如下:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at A.A.main(A.java:9)現在程式是很簡單,不過如果在大型項目里爆了堆溢出可就麻煩了。
我們很難通過程式碼定位。
所以我們需要用工具對其分析。
二、堆記憶體快照
我們先對Eclipse進行運行配置。
參數如下所示
-XX:+HeapDumpOnOutOfMemoryError -Xms20m -Xmx20m
運行結果如下:
隨後我們找到項目地址,我們會發現在Project本目錄中出現了個hprof文件
至此我們就把堆記憶體快照保存下來了。
三、分析
我們這裡需要一個工具叫MAT是Eclipse提供的分析工具。
這裡是鏈接我們選擇清華的鏡像
解壓後運行
這裡運行會很慢,需要等待很久。打開後如下所示。
用這個工具把我們之前dump下來的東西放進去
點開dominator_tree,我們會發現問題儲在main執行緒里,
這裡有倆參數,一個是Shallow Heap,另一個是Retained Heap
shallowHeap | Retained Heap |
---|---|
對象本身佔用的記憶體大小 | 對象本身佔用的大小+對象引用的大小總和 |
常規理解就是如果我們對其做GC,那麼就會釋放掉這麼大的記憶體。
而其中的這個Object對象就是我們之前創建的String類