本文演示如何通過ATP的Java堆分析,尋找應用出現內存不足錯誤的原因。
1. 生成數據源并上傳至ATP
假設我們觀察到生產環境中的應用出現如下內存不足的報錯:
java.lang.OutOfMemoryError: Java heap space
Exception in thread "Thread-3" Exception in thread "Thread-1" java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: Java heap space
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
Exception in thread "Thread-6" java.lang.OutOfMemoryError: Java heap space
這時我們可以生成應用的Heap dump文件,并將它上傳到ATP,然后開始分析(具體操作參見開始使用ATP)。
2. 使用ATP堆分析
分析結果界面如下。通常我們會先查看【綜合報表】查看堆大小、生成時間、JDK版本等信息,排除誤操作,確認該文件和我們要分析的應用匹配。
然后進入【對象報表】界面,發現【class App @ 0x716500ed0】占據了堆中99.9%的內存,但是這是一個類,類本身不會占用很多內存,所以我們繼續單擊我引用誰,查看這個類引用的數據:
此時我們可以看到,實際上是App這個類有一個ConcurrentHashMap靜態字段,這個容器持有3.76GB內存。
展開ConcurrenthashMap的節點,它的key是Integer類型,val是App$Holder類型,右側顯示App$Holder這個對象有兩個字段:data、processed。
接著單擊class App對象,從右側可以知道它有一個靜態字段queue。
3. 結論
根據以上收集到的信息,我們可以部分還原出問題的Java代碼,大概如下:
class App {
static class Holder {
public boolean processed;
byte[] data = new byte[1024 * 1024 * 50];
}
// 3.76GB
static ConcurrentHashMap<Integer, Holder> queue = new ConcurrentHashMap<>();
}
即queue這個容器持有大量內存,結合具體Java源碼,到這里我們基本上就能排查出問題了。
文檔內容是否對您有幫助?