排查Java 記憶體洩露-藉助排查工具
阿新 • • 發佈:2018-11-19
轉自:https://juejin.im/entry/57fb07255bbb50005b2f20ac
java記憶體洩露典型特徵
- 現象一: 堆/Perm 區不斷增長, 沒有下降趨勢(回收速度趕不上增長速度), 最後不斷觸發FullGC, 甚至crash(如下**兩張圖是同一個應用的GC和Perm資料, GC觸發原因確認是Perm不足**) . 一般是現象二的晚期表現.
java記憶體洩露場景---PermGen space
-
原因:
-
案例: Groovy動態編譯class, xstream String.intern
-
本質原因: ClassLoader.defineClass和java.lang.String.intern在大量不適宜的場景被呼叫.
-
**解決方案: **
-
方案1(直接有效): 使用btrace相關工具輸出呼叫ClassLoader.defineClass棧資訊, 從棧資訊來追溯問題. (程式碼如下圖). 但Btrace 不能trace jvm native方法(官方release btrace 1.3.1中版本宣告可以trace native方法, 但嘗試無效。如果你清楚如何使用,麻煩告知一下,謝謝).
- **用JProfiler來trace String.intern方法棧
-
方案2: dump heap, 看看哪些class有異常現象(數量), String被Perm區引用的物件資訊等.但這種方式不太直觀,可以從String資料看看發現可疑問題,沒有方案1直觀。(如下圖: 如果能在日常除錯推薦JProfiler**)
-
java記憶體洩露場景---Java heap space
-
原因: 長生命週期的物件引用了短生命週期(應該儘快GC回收掉)的物件,最後造成一個物件已經不能在堆區分配足夠空間. 注: 這種現象不能完全肯定是記憶體洩露, 比如: heap本身的設定的過小.
-
案例: 我個人沒有遇到過這種案例, 但模擬過這種情形的Demo: 參考我的《深入淺出JProfiler》文章, 也學習過其他同學的案例: 例如:引數過大並且頻繁超時導致記憶體洩露
-
解決方案:
- 觸發FullGC, dump live heap. 標記堆中物件數量, 重點關注可疑物件
- 觸發FullGC, dump live heap. 標記堆中物件數量, 重點關注可疑物件
- 對比步驟1和步驟2 相同物件的數量和大小, 找出可疑物件一一進行排查確認。
- 如果步驟3依然無法明確有問題的物件, 那就多執行幾次步驟1和步驟2。 在此過程中可以調整GC觸發時間, 模擬真實的故障場景 :)
- 看看GC後堆的大小是否增長, 如果沒有不斷增長, 並且持續一段較長時間, 那基本正常(具體看看[深入淺出JProfiler][JProfiler]文章中的實踐章節)。