2015-11-19 45 views
3

我有兩臺linux機器(都是VM),一臺有12GB內存,另一臺有8GB內存。Java:什麼決定了linux機器中可能的最大堆大小

我試圖在兩臺機器上啓動相同的java程序,儘可能使用最大堆大小(使用-Xmx標誌)。以下是我得到的結果。

  • 12GB機:9460MB
  • 8GB機:4790MB

如果我指定一個最大堆大小超出上述限額的,我得到下面的錯誤。

Error occurred during initialization of VM 
Could not allocate metaspace: 1073741824 bytes 

我檢查了釋放內存在兩個系統(使用free命令),和我有以下。

  • 12GB機器:約3GB免費。
  • 8GB機器:約4GB免費。

我的問題是,什麼決定了Java程序可以啓動的最大最大堆大小,這不會導致上述錯誤? (當程序給出上述錯誤時,系統有足夠的內存來分配1073741824字節的內存)

+0

什麼是您的JDK版本? 64位或32位? –

+0

@ravindra jdk1.8.0_40,64bit –

+0

你也設置了元空間嗎?你能發佈完整的虛擬機選項嗎? –

回答

1

我做了一些實驗,通過拉溫德拉提供的線索,發現最大最大堆大小與系統中可用的虛擬內存總量有直接的關係。在系統

總虛擬存儲器可以(在KB)中找到與:

ulimit-v 

總虛擬存儲器可以與被改變:

ulimit -v <new amount in KB> 

最大最大堆尺寸可能爲約2GB比虛擬內存少。如果使用ulimit -v unlimited指定無限虛擬內存,則可以爲最大堆大小指定任何較大的值。

0

您可用的內存是可用RAM和交換空間的組合。這也取決於系統是否啓用了overcommit - 如果是這樣,內核將允許程序分配比實際可用內存更多的內存(在合理限制內),因爲程序通常分配的實際數量比實際使用的要多。

請注意,overcommit默認情況下處於啓用狀態。要將其禁用,請將2寫入/proc/sys/vm/overcommit_memory。 (奇怪的是,0的值並不意味着「沒有過量使用」。)但是,首先閱讀overcommit文檔是個好主意。

3

我在JDK版本9中發現有趣的評論來自JDK bug(的錯誤,而不是在8它說錯誤是固定在8.x的版本,但並沒有告訴小的集結號。

如果虛擬內存已限制使用「的ulimit -v」,並且服務器有大量的RAM,那麼JVM無法啓動,而無需額外的命令行參數GC

// After "ulimit -v" The jvm does not start with default command line. 
$ ulimit -S -v 4194304 
$ java -version 
Error occurred during initialization of VM 
Could not allocate metaspace: 1073741824 bytes 

點評:

問題似乎是我們必須指定MALLOC_ARENA_MAX。

如果我設置環境變量MALLOC_ARENA_MAX = 4,那麼jvm可以在沒有任何額外參數的情況下啓動。

我想這不是可以從jvm修復的東西。如果是的話,我們可以關閉這個bug。

當使用「UseConcMarkSweepGC」時,上面的命令行不起作用。 我試圖添加MaxMetaspaceSize = 128m,但它沒有幫助。 我相信有一個說法可以使它工作,但我還沒有找到一個。 使用有限的虛擬內存配置GC不是非常方便用戶使用。

根據您的要求更改參數並嘗試這一個。

ulimit -S -v 4194304 
java -XX:MaxHeapSize=512m -XX:InitialHeapSize=512m -XX:CompressedClassSpaceSize=64m -XX:MaxMetaspaceSize=128m -XX:+UseConcMarkSweepGC -version 
+0

導出MALLOC_ARENA_MAX = 4似乎無法解決我的問題。 – par

+0

使用'ulimit -v 4193280'生效時,獲取版本字符串的最小值似乎爲:'java -XX:MaxHeapSize = 1m -XX:MaxMetaspaceSize = 8m -version'(JDK 1.8.0_144) –

相關問題