1. 程式人生 > 其它 >Java記憶體問題分析與定位

Java記憶體問題分析與定位

簡介

 

  •  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負載很高

分析與解決:

  1. 超時或負載高很可能是GC異常表象,此時需要檢視GC日誌,結合實際業務,分析GC行為,找到GC異常根因。
  2. GC頻繁,STW時間長,可能原因有:存活物件多,堆大小或堆各子區域大小劃分不合理。
  3. 存活物件多,則可能存在記憶體洩漏,可能是程式碼邏輯問題,進一步可用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記憶體

 

堆內記憶體洩漏排查