2014-01-21 122 views
14

我真的很困惑這一點。

Xmx根據java文檔,是最大允許的堆大小。
Xms是必需的最小java堆大小,並且在JVM啓動時分配。

在32位JVM(4GB RAM)上,java -Xmx1536M HelloWorld給出了無法分配足夠的內存錯誤的問題。
在64位JVM(4GB Ram)上,java -Xmx20G HelloWorld工作得很好。但我沒有分配太多的虛擬或物理內存。

因此,我得出這樣的結論:Java 32位在JVM啓動時分配1536M,但Java 64位不是。

爲什麼?一個簡單的Hello World應該不需要1536M運行。我只是說明1536M是最大的,並不是它需要的。

解釋任何人?Java 32位Xmx與Java 64位Xmx

回答

7

實際上,應用程序在啓動時未分配Xmx內存。

-Xms參數配置啓動內存。 (What are the Xms and Xmx parameters when starting JVMs?

64位環境允許更大的內存分配,然後32位。但事實上,它使用的是HD空間,而不是內存RAM。

看到這個其他職位的更多信息。

Estimating maximum safe JVM heap size in 64-bit Java

+4

+1對於32位Linux,您可以執行'java -Xmx3g',它是Windows 32位,它具有有限的連續地址空間。 –

18

有分配內存和分配的地址空間之間的區別。 Oracle JVM在啓動時分配地址空間以確保堆是連續的。這允許對堆使用某些優化。

如果分配失敗,那麼Java將不會啓動......如您所見。它不一定使用那麼多的內存,但是它預先分配了所需的地址空間。既然你通過了-Xmx1536m,那就說好,我需要分配它以防萬一你需要它...因爲它必須是連續的,所以它可以保證它(或嘗試失敗)。

此行爲在32位和64位JVM上都是相同的。您所看到的是32位進程的每進程2GB地址空間限制(至少,在Windows上,這是限制 - 在其他平臺上可能稍大),導致此分配在32位上失敗,其中64由於它具有更大的地址空間,因此它沒有問題。但是,你說,1536米小於2GB,我應該很好,對吧?不完全 - 堆不是唯一的東西在地址空間中分配,DLL和其他東西也分配在地址空間...所以不幸的是,在32位上獲得2GB最大連續的1536米塊是不太可能的。我發現低於1000米的值在32位進程上出現故障並且碎片特別差,通常1200-1300米是您可以在32位上指定的最大堆。

在現代操作系統上,ASLR(地址空間佈局隨機化)使32位進程地址空間的分割變得更糟。它出於安全原因故意將DLL加載到隨機地址中......使得它更不可能在32位中獲得大而連續的堆。

在64位中,地址空間非常大以致碎片不再成爲問題,可以毫無問題地分配巨量堆。即使你在32位上有4GB的內存,但每進程地址空間限制2GB(至少在Windows上)通常意味着最大堆通常只有1300m左右。

2

在Windows下,與VirtualAlloc等原生WinAPI低級函數在內存分配操作上存在差異。

「保留」意味着分配進程地址空間中的連續區域,而不實際使該區域的虛擬內存可用。分配的區域不支持實際的物理RAM或交換空間,也不佔用任何可用內存。任何應用程序都可以保留任何數量的地址空間,僅限於處理器的內存尋址能力(位數)。

「承諾」意味着支持一些先前「保留」的內存與實際內存 - 內存或交換空間,使其實際可讀/寫的過程。該內存取自可用的操作系統虛擬內存池(RAM和交換)。

「提交」內存(從池中取空白頁)的替代方法是將文件「映射」到先前「保留」的內存中。這不會佔用交換池中的內存,而是以類似於進程地址空間特定區域的專用交換空間的方式使用映射文件。

本機Windows應用程序(如JVM本身)爲將來所需的所有堆保留內存,但僅在需要時才提交。 像malloc()風格的函數或「新」運算符這樣的高級內存操作確實會根據需要進行「提交」,甚至會自行執行堆管理邏輯用戶模式,並提供大塊內存,因爲這是CPU密集型內核調用並在頁面(4k)粒度下工作。

進程啓動期間JVM「保留」-Xmx內存,但僅「提交」-Xms數量。隨着堆的增長,剩餘的保留內存按需提供。所以堆可以增長到可用內存或-Xmx參數,以較小者爲準。