通過 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。
參考:http://www.ibm.com/developerworks/cn/java/j-codetoheap/#iratings