jvm探查內存不足/內存泄漏問題

探查內存不足/內存泄漏問題
 
問題描述

內存不足 (OOM) - 由於 java 堆或本地內存中的內存耗盡,應用程序顯示“內存不足”錯誤。

內存泄漏 - java 堆或本地內存的持續內存增長,最終將導致內存不足狀態。調試內存泄漏狀態的技術與調試內存不足狀態的技術相同。

故障排除
請注意,並非下面所有任務都需要完成。有些問題僅通過執行幾項任務就可以解決。

快速鏈接:

Java 堆、本地內存和進程大小
進程地址空間和物理內存之間的差異
爲什麼會發生 OOM 問題,JVM 在這種情況下如何處理?
排除故障的步驟
確定是 Java OOM 還是本地 OOM
Java OOM
本地 OOM
Jrockit 特定特性
參考文獻
Java 堆、本地內存和進程大小

Java 堆 - 這是 JVM 用來分配 java 對象的內存。java 堆內存的最大值用 java 命令行中的 .Xmx 標誌來指定。如果未指定最大的堆大小,那麼該極限值由 JVM 根據諸如計算機中的物理內存量和該時刻的可用空閒內存量這類因素來決定。始終建議您指定最大的 java 堆值。

本地內存 - 這是 JVM 用於其內部操作的內存。JVM 將使用的本地內存堆數量取決於生成的代碼量、創建的線程、GC 期間用於保存 java 對象信息的內存,以及在代碼生成、優化等過程中使用的臨時空間。

如果有一個第三方本地模塊,那麼它也可能使用本地內存。例如,本地 JDBC 驅動程序將分配本地內存。

最大本地內存量受到任何特定操作系統上的虛擬進程大小限制的約束,也受到用 .Xmx 標誌指定用於 java 堆的內存量的限制。例如,如果應用程序能分配總計爲 3 GB 的內存量,並且最大 java 堆的大小爲 1 GB,那麼本地內存量的最大值可能在 2 GB 左右。 進程大小 - 進程大小將是 java 堆、本地內存與加載的可執行文件和庫所佔用內存的總和。在 32 位操作系統上,進程的虛擬地址空間最大可達到 4 GB。從這 4 GB 內存中,操作系統內核爲自己保留一部分內存(通常爲 1 - 2 GB)。剩餘內存可用於應用程序。

Windows缺省情況下,2 GB 可用於應用程序,剩餘 2 GB 保留供內核使用。但是,在 Windows 的一些變化版本中,有一個 /3GB 開關可用於改變該分配比率,使應用程序能夠獲得 3 GB。有關 /3GB 開關的詳細信息,可以在以下網址中找到:
http://msdn.microsoft.com/library/default.asp?url=/library/en-
us/ddtools/hh/ddtools/bootini_1fcj.asp

RH Linux AS 2.1 - 3 GB 可用於應用程序。

對於其它操作系統,請參考操作系統文檔瞭解有關配置。

返回頁首

進程地址空間和物理內存之間的差異

每個進程都獲得其自有的地址空間。在 32 位操作系統中,此地址空間範圍爲 0 到 4 GB。此範圍與計算機的可用隨機存取內存 (RAM) 或交換空間無關。計算機中的可用物理內存總量是該計算機上的可用 RAM 和交換空間之和。所有運行的進程共享這些物理內存。

進程內的存儲地址是虛擬地址。內核將此虛擬地址映射到物理地址上。物理地址指向物理內存中的某個位置。在任一給定時間,計算機中運行進程所使用的全部虛擬內存的總和不能超過該計算機上可用物理內存的總量。

返回頁首

爲什麼會發生 OOM 問題,JVM 在這種情況下如何處理?

java 堆中的內存不足
如果 JVM 不能在 java 堆中獲得更多內存來分配更多 java 對象,將會拋出 java 內存不足 (java OOM) 錯誤。如果 java 堆充滿了活動對象,並且 JVM 無法再擴展 java 堆,那麼它將不能分配更多 java 對象。

在這種情況下,JVM 讓應用程序決定在拋出 java.lang.OutOfMemoryError 後該執行什麼操作。例如,應用程序可以處理此錯誤,並決定以安全方式自行關閉或決定忽略此錯誤。如果應用程序不處理此錯誤,那麼拋出此錯誤的線程將退出(如果您進行 java Thread Dump,那麼將看不到該線程)。

在使用 Weblogic Server 的情況下,如果此錯誤是由某個執行線程拋出的,則會處理此錯誤並將其記錄在日誌中。如果連續拋出此錯誤,那麼核心運行狀況監視器線程將關閉 Weblogic Server。

本地堆中的內存不足
如果 JVM 無法獲得更多本地內存,它將拋出本地內存不足(本地 OOM)錯誤。當進程到達操作系統的進程大小限值,或者當計算機用完 RAM 和交換空間時,通常會發生這種情況。

當發生這種情況時,JVM 處理本地 OOM 狀態,記錄說明它已用完本地內存或無法獲得內存的消息,然後退出。如果 JVM 或加載的任何其它模塊(如 libc 或第三方模塊)不處理這個本地 OOM 狀態,那麼操作系統將給 JVM 發送命令 JVM 退出的 sigabort 信號。通常情況下,JVM 收到 sigabort 信號時將會生成一個核心文件。

返回頁首

排除故障的步驟

確定是 Java OOM 還是本地 OOM:
如果 stdout/stderr 消息說明這是一個 java.lang.OutOfMemoryError,那麼這就是 Java OOM
如果 stdout/stderr 消息說明無法獲得內存,那麼這就是本地 OOM
請注意,上述消息僅發送到 stdout 或 stderr 中,而不發送到應用程序特定的日誌文件(如 weblogic.log)

返回頁首

對於 Java OOM:

收集和分析 verbose gc 輸出
在 java 命令行中添加“-verbosegc”標誌。這樣將會把 GC 活動信息打印到 stdout/stderr。將 stdout/stderr 重定向到一個文件。運行應用程序,直到該問題重現。
確保 JVM 在拋出 java OOM 之前完成下列任務完整 GC 運行:
執行一次完整 GC 運行,並且刪除了所有不可及對象以及虛可及、弱可及、軟可及對象,並回收了那些空間。有關不同級別的對象可及性的詳細信息,可以在以下網址中可找到:
http://java.sun.com/developer/technicalArticles/ALT/RefObj

您可以檢查是否在發出 OOM 消息之前執行了完整 GC 運行。當完成一次完整 GC 運行時,將會打印類似如下消息(格式取決於 JVM - 請查看 JVM 幫助信息以瞭解有關格式)

[memory ] 7.160: GC 131072K->130052K (131072K) in 1057.359 ms

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章