Java進程的內存使用情況

通過 java 命令執行 class 程序或者啓動基於 Java 的中間件(Weblogic、Workshop、Eclipse、SQL Developer)時,Java運行時會創建一個操作系統進程,就像運行基於C的程序時一樣,可以通過JPS命令查看到。

作爲操作系統進程,Java 運行時面臨着與其他進程完全相同的內存限制:操作系統架構提供的可尋址地址空間和用戶空間。

操 作系統架構提供的可尋址地址空間,由處理器的位數決定,32 位提供了 2^32 的可尋址範圍,也就是 4,294,967,296 位,或者說 4GB。而 64 位處理器的可尋址範圍明顯增大:2^64,也就是 18,446,744,073,709,551,616,或者說 16 exabyte(百億億字節)。

地址空間被劃分爲用戶空間和內核空間。內核是主要的操作系統程序和C運行時,包含用於連接計算機硬件、調度程序以及提供聯網和虛擬內存等服務的邏輯和基於C的進程(JVM)。除去內核空間就是用戶空間,用戶空間纔是 Java 進程實際運行時使用的內存

默認情況下,32 位 Windows 擁有 2GB 用戶空間和 2GB 內核空間。在一些 Windows 版本上,通過向啓動配置添加 /3GB 開關並使用 /LARGEADDRESSAWARE 開關重新鏈接應用程序,可以將這種平衡調整爲 3GB 用戶空間和 1GB 內核空間。在 32 位 Linux 上,默認設置爲 3GB 用戶空間和 1GB 內核空間。一些 Linux 分發版提供了一個hugemem內核,支持 4GB 用戶空間。爲了實現這種配置,將進行系統調用時使用的地址空間分配給內核。通過這種方式增加用戶空間會減慢系統調用,因爲每次進行系統調用時,操作系統必須在地址空間之間複製數據並重置進程地址-空間映射。

下圖爲一個32 位 Java 進程的內存佈局:

 

可尋址的地址空間總共有 4GB,OS 和 C 運行時大約佔用了其中的 1GB,Java 堆佔用了將近 2GB,本機堆佔用了其他部分。請注意,JVM 本身也要佔用內存,就像 OS 內核和 C 運行時一樣。

注意:

1. 上文提到的可尋址空間即指最大地址空間。

2. 對於2GB的用戶空間,理論上Java堆內存最大爲1.75G,但一旦Java線程的堆達到1.75G,那麼就會出現本地堆的Out-Of-Memory錯誤,所以實際上Java堆的最大可使用內存爲1.5G。

---------------

深入理解Java堆內存分配策略(Xmx和Xms)

例子:-Xmx=512M -Xms=64M

Java堆可以通過Xmx和Xms兩個參數指定最大內存512M,最小內存64M。以下爲兩個常見疑問:

1. 既然都指定了 Xmx 爲什麼還要設置 Xms 呢?

Xms 是必不可少的配置,Xms 是 GC 算法進行垃圾收集評判標準中一個必不可少的元素。另外-Xms和-Xmx設置相同時可避免Java堆自動擴展。

2. Xmx 指定的最大 Java 堆內存是在 Java 進程啓動的時候直接一次性分配還是隨着堆內存消耗不斷增加直到 Xmx?

Xmx的內存是在Java進程啓動的時候直接分配(預留)的,而不是不斷增加的。因爲大部分 GC 算法依賴於被分配爲連續的內存塊的堆,因此不能在堆需要擴大時再分配更多本機內存。所有堆內存必須預先保留。

對於例子中的Xmx=512M是直接預留出512M的內存空間,但啓動時的Java進程並不一定全部使用,但512M是它的“領地”。

注意:

1. 對於問題2的提問其實有錯誤,Xmx指定內存並不是真正的分配,而是一種保留,內存保留 != 內存分配當本機內存被保留時,無法使用物理內存或其他存儲器作爲備用內存。儘管保留地址空間塊不會耗盡物理資源,但會阻止內存被用於其他用途。由保留從未使用的內存導致的泄漏與泄漏分配的內存一樣嚴重。


發佈了30 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章