簡體   English   中英

eclipse 內存分析器看到整個堆轉儲 (8GB) 的一小部分 (363,2MB)

[英]eclipse memory analyzer sees small part (363,2MB) of entire heap dump (8GB)

我試圖調查java.lang.OutOfMemoryError: GC limit exceeded發生在我們部署在 tomcat 中的 Web 應用程序的高負載時。 堆大小設置為 8GB ( -Xms2048m -Xmx8192m )

在某個時間點,由於 GC 活動開銷,我們的應用程序變得無響應。 我可以在日志中看到 Full GC 連續發生多次。 所以我使用以下命令( jmap -F -dump:format=b,file=/root/dump2.hprof 4963 )進行了堆轉儲。 包含轉儲的文件大小為 9GB。 在進行轉儲后(應用程序被凍結了大約 45 分鍾),發生了多次完整的 GC,直到OutOfMemoryError

這是 GC 活動的日志示例

[Full GC [PSYoungGen: 932096K->875513K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6467961K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.3954040 secs] [Times: user=47.60 sys=0.43, real=12.39 secs]
[Full GC [PSYoungGen: 932096K->890562K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6483009K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.6131900 secs] [Times: user=48.45 sys=0.49, real=12.61 secs]
[Full GC [PSYoungGen: 932096K->895268K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6487715K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 12.9488670 secs] [Times: user=49.61 sys=0.46, real=12.95 secs]

Heap
 PSYoungGen      total 1864128K, used 896698K [0x0000000755560000, 0x0000000800000000, 0x0000000800000000)
  eden space 932096K, 96% used [0x0000000755560000,0x000000078c10e8a8,0x000000078e3a0000)
  from space 932032K, 0% used [0x000000078e3a0000,0x000000078e3a0000,0x00000007c71d0000)
  to   space 932032K, 0% used [0x00000007c71d0000,0x00000007c71d0000,0x0000000800000000)
ParOldGen       total 5592448K, used 5592447K [0x0000000600000000, 0x0000000755560000, 0x0000000755560000)
  object space 5592448K, 99% used [0x0000000600000000,0x000000075555ff30,0x0000000755560000)
PSPermGen       total 262144K, used 112285K [0x00000005e0000000, 0x00000005f0000000, 0x0000000600000000)
  object space 262144K, 42% used [0x00000005e0000000,0x00000005e6da7530,0x00000005f0000000)

heap dump is taken (ca 45minutes freeze)
[Full GC [PSYoungGen: 932096K->903362K(1864128K)] [ParOldGen: 5592447K->5592447K(5592448K)] 6524543K->6495810K(7456576K) [PSPermGen: 112285K->112285K(262144K)], 2883.9864390 secs] [Times: user=49.41 sys=0.47, real=2884.17 secs]
[Full GC [PSYoungGen: 932096K->897728K(1864128K)] [ParOldGen: 5592447K->5592444K(5592448K)] 6524543K->6490173K(7456576K) [PSPermGen: 112288K->112288K(262144K)], 13.3092680 secs] [Times: user=50.75 sys=0.40, real=13.31 secs]

為了分析堆轉儲,我在 eclipse 內存分析器 (MAT) 中打開了它。 不幸的是,MAT 顯示堆大小為 363.2MB(在概覽選項卡或堆轉儲詳細信息選項卡中),而根據 GC 日志,堆已填充到 6467961K(6.4G)。 Unreachable Objects Histogram 顯示總共 75 511 736 (75 MB)。 直方圖視圖也確認淺堆總數為 380 837 136 (363.2MB)

我的問題是,如果 GC 無法回收內存,為什么 MAT 不顯示堆轉儲中的所有對象?

env details:
Eclipse Memory Analyzer Version 1.2.1
heap dump taken on
java version "1.7.0_13"
Java(TM) SE Runtime Environment (build 1.7.0_13-b20)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

以下是 MAT 中導入的堆轉儲的屏幕截圖:

默認情況下,MAT 不顯示無法訪問的對象。

您可以通過轉到 Preferences -> Memory Analyzer -> Keep Unreachable Objects 來啟用該選項。 啟用該選項后再次加載堆。

啟用該選項后,它將顯示完整的堆。 即使我處於同樣的情況並且無法在網上獲得太多信息,我的經理向我展示了這個選項。希望它有幫助。

這是MAT 在收集如此大堆的堆轉儲時的常見行為 我經常收集 8GB 堆的堆轉儲,通常會得到一個顯示大約 1GB 活動對象的 MAT 配置文件。

預計還會出現 45 分鍾的凍結。 我的解釋是,在堆轉儲收集期間,會發生幾個FullGC 循環,這會減小所獲得的實際堆轉儲的大小 但我還沒有找到官方解釋或參考文獻記錄為什么會有這么大的差異。

此外,請參閱此參考資料 - MAT 不顯示完整堆

症狀:以交互方式監視內存使用情況時,使用的堆大小比 MAT 報告的要大得多。

在創建索引期間,Memory Analyzer 會移除無法訪問的對象,因為各種垃圾收集器算法往往會留下一些垃圾(如果對象太小,移動和重新分配地址的成本會很高)。 但是,這不應超過 3% 到 4%。 如果您想知道刪除了哪些對象,請按照此處的說明啟用調試輸出: MemoryAnalyzer/FAQ#Enable_Debug_Output

實際上,當您對java.lang.OutOfMemoryError: GC limit exceeded問題進行故障排除時,我不建議您使用 jmap 實用程序。 當 JVM 正在銷毀(過多的主要集合)時,我已經看到了這種方法的問題。

請改為嘗試以下方法,看看您是否從 MAT 解析和分析過程中獲得更好的結果:

  • 添加以下JVM HotSpot參數-XX:+HeapDumpOnOutOfMemoryError
  • 再次復制問題,等待OOM事件。 堆轉儲生成應該快得多,這將增加數據的價值和有效性。
  • 然后,JVM 將在 OOM 事件之后生成JVM Heap Dump (HPROF 格式)。
  • 在 MAT 中再次加載 JVM 堆轉儲,看看是否獲得了更好的結果,例如更大的堆占用空間。

問候, PH

我們最近在 MAT 中發現了一個錯誤,它只能看到堆的一個子集: https : //bugs.eclipse.org/bugs/show_bug.cgi? id =404679#c3

問題是 JVM 寫入了一個超過 4GB 的 HEAP_DUMP 記錄,因此頭中的長度被包裹。

你運行的是什么版本的MAT? 請嘗試更新的版本。

默認情況下,MAT 從其視圖中隱藏所有Unreachable 對象,因為這些對象已經被標記為垃圾收集。

可以在以下視圖中訪問無法訪問的對象:

  1. 關閉快照
  2. 使用 Window > Heap Dump History 右鍵單擊​​選擇堆轉儲,刪除索引文件
  3. 使用 Window > Preferences > Memory Analyzer 選擇“Keep unreachable objects”
  4. 重新打開堆轉儲,這將重新解析堆轉儲。
  5. 選擇 Java Basics > GC Roots 查詢。
  6. 選擇“無法訪問的對象”行。
  7. 在該行上運行“顯示保留集”查詢。

這將顯示所有通常無法訪問的對象的直方圖,並且將在下一次機會被垃圾收集。 由於這些對象現在位於快照中,因此可以更詳細地檢查它們。

有關詳細信息,請參閱: Eclipse MAT 參考 - 無法訪問的對象

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM