簡體   English   中英

為什么我的Java堆轉儲大小比使用的內存小得多?

[英]Why is my Java heap dump size much smaller than used memory?

問題

我們正試圖在我們的Web應用程序中找到大內存泄漏的罪魁禍首。 我們在查找內存泄漏方面經驗非常有限,但我們發現了如何使用jmap創建Java堆轉儲並在Eclipse MAT中對其進行分析。

但是,我們的應用程序使用56 / 60GB內存,堆轉儲的大小只有16GB,在Eclipse MAT中甚至更少。

上下文

我們的服務器在Ubuntu 14.04上使用Wildfly 8.2.0作為我們的Java應用程序,其進程使用95%的可用內存。 進行轉儲時,我們的緩沖區/緩存已用空間為56GB。

我們使用以下命令創建轉儲: sudo -u {application user} jmap -dump:file=/mnt/heapdump/dump_prd.bin {pid}

堆轉儲文件大小為16,4GB,當使用Eclipse MAT進行分析時,它表示有大約1GB的活動對象和大約14,8GB的無法訪問/淺堆。

編輯:這里有一些關於我們看到的問題的更多信息。 我們監視內存使用情況,我們看到它的增長和增長,直到剩下大約300mb的可用內存。 然后它保持在那個內存量附近,直到進程崩潰,不幸的是在應用程序日志中沒有錯誤。

這使我們假設它是一個硬OOM錯誤,因為這只發生在內存接近耗盡時。 我們為JVM使用-Xms25000m -Xmx40000m設置。

基本上,我們想知道為什么我們的大部分內存都沒有在這個轉儲中被捕獲。 頂部保留的大小類看起來並不太可疑,所以我們想知道是否存在與堆轉儲有關的問題我們做錯了什么。

轉儲堆時,JVM將首先運行垃圾收集周期以釋放任何無法訪問的對象。

如何在沒有垃圾收集的情況下在Java 5上進行堆轉儲?

根據我的經驗,在一個真正的OutOfMemoryError中,你的應用程序只需要比可用的更多的堆空間,這個GC是一個傻瓜的差事,最后的堆轉儲將是最大的。 堆大小。

當堆轉儲小得多時,這意味着系統不是真正的內存不足,但可能有內存壓力。 例如,存在java.lang.OutOfMemoryError: GC overhead limit exceeded錯誤,這意味着JVM可能已經能夠釋放足夠的內存來為一些新的分配請求提供服務,但它必須花費太多時間來收集垃圾。

您也可能沒有內存問題。 是什么讓你覺得你這樣做? 您沒有提到任何有關堆使用或OutOfMemoryError的內容。 您剛才提到了JVM在操作系統上的內存占用。

根據我的經驗,使用比實際內存小得多的堆轉儲可能是由於JNI中的泄漏。

盡管您不直接使用任何本機代碼,但某些庫可以使用它來加速。

在我們的例子中, DeflaterInflater沒有正確結束。

暫無
暫無

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

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