Java記憶體問題分析與定位
阿新 • • 發佈:2022-05-05
簡介
- JNI方法申請的native 記憶體,通常是在JDK庫裡;本地 C++ 方法直接通過 malloc申請的記憶體,不受JVM管控。
- 堆內記憶體: 指Java堆,GC演算法管理的記憶體區域。
- 堆外記憶體: Java堆外的記憶體都叫堆外。可以細分為JVM內部,Metaspace, JNI方法申請的native記憶體三部分。通常說的直接記憶體 DirectBuffer , 會記錄在Internal區。
JNI申請的native記憶體不受JVM管控。
GC演算法和日誌解讀
- Java堆進一步劃分,Eden, s0, s1, 老年代。
- 不同GC演算法對存活物件的掃描和清理方式不一樣,對業務程式碼的執行影響不一樣,因此,不同的業務場景,選合適的GC演算法和GC引數。
一般建議 parallel scavenge (JDK8預設GC),適用大部分場景。
GC日誌組成: GC時間, GC原因, GC位置(年輕代, 老年代, 元空間), 釋放記憶體大小, 持續時間。
原則上, 優先看Full GC的頻率, 其次檢視日誌STW階段(比如G1裡標記了pause, CMS裡mark和remark)階段消耗時間,
最後檢視記憶體收縮情況。
用JMap工具可以轉儲Java堆到快照檔案,然後用MAT工具分析,只要是堆內問題,就用MAT工具。
- 可以詳細檢視Java堆內java物件佔比
- 可多維度分析堆內物件分佈,查詢可疑的記憶體最大佔比的物件。
- 可分析物件的依賴路徑,查詢為是否原因。
GC異常分析與定位
現象:
- 業務偶爾出現超時現象
- cpu負載很高
分析與解決:
- 超時或負載高很可能是GC異常表象,此時需要檢視GC日誌,結合實際業務,分析GC行為,找到GC異常根因。
- GC頻繁,STW時間長,可能原因有:存活物件多,堆大小或堆各子區域大小劃分不合理。
- 存活物件多,則可能存在記憶體洩漏,可能是程式碼邏輯問題,進一步可用MAT工具分析Java物件。
OOM問題分析與定位
1. 根據OOM錯誤提示,由於配置原因導致Java堆或者Metaspace區域oom,
判斷標準之一是程式是否穩定執行,實際記憶體佔用有升有降。
2. Metaspace本身沒有限制,如果設定了MaxMetaspaceSize,則受限這個配置。
3.如果記憶體持續增長超出業務實際可能使用的記憶體量,則可能存在記憶體洩漏。
記憶體洩漏位置判斷
1. 通過異常日誌提示,
eg, Java.lang.OutOfMemoryError: Java heap space,
Java.lang.OutOfMemoryError: metadata space,
Java.lang.OutOfMemoryError: Direct buffer space,
2. 開啟NMT(啟動引數上加上 -XX: NativeMemoryTracking=detail), 可幫助判斷那塊記憶體區域記憶體洩漏。
- Java堆,即Java Heap
- Metaspace, 即class區域
- JVM內部
- JNI申請的native記憶體
堆內記憶體洩漏排查