
在 Redhat CentOS 6.4 上,只有幾個進程在運行,使用大約 3GB RAM(系統有 12GB 可用)。其中一個進程是 WSO2ESB 伺服器(java),我們使用這些參數啟動它:
-Xms2048m -Xmx3072m
一段時間後,我們收到 OutOfMemory 異常,但是java行程(WSO2ESB)行程甚至沒有使用它的3GB。在 jconsole 中,您還可以看到這些參數設定正確(此時 Linux 伺服器大約有 9GB 可用 RAM)
Linux 不給我們配置 3 GB RAM 嗎?
在完全相同的 Windows 安裝上 - java 進程可以使用它的 3GB RAM,沒有任何問題。
jconsole 的螢幕截圖顯示堆疊記憶體使用量僅在 0.3 到 1.0 GB 之間。當發生 OutOfMemory 異常時,堆內存為 0.5GB,但該進程將有 3GB 可以使用,但它並沒有...
編輯:新增了java進程的日誌:
java.lang.OutOfMemoryError: unable to create new native thread
EDIT2:新增了免費 -m 輸出:
答案1
我解決了這個問題。 wso2esb 使用了超過 1000 個執行緒。但在 Linux 上,用戶可以使用的預設線程數設定為 1024。
為此:打開 /etc/security/limits.conf 並為您的用戶添加以下兩行:
myuser soft nproc 8192
myuser hard nproc 8192
答案2
Java堆空間有多代、新、舊永久代。
如果您將 Xmx 設定得非常高,則該值將用於堆,即使您不使用整個堆,也可能會耗盡記憶體。如果您用完 PermGen 空間,通常會發生這種情況。
永久代堆用於儲存String池以及JVM所需的與Class、方法等java原語相關的各種Meta資料。 Perm 空間通常為 64MB,因此如果您有很多類別或巨大的字串,您可能會用完它。
嘗試透過新增以下內容來增加永久代大小:
-XX:MaxPermSize=256m
到你的java啟動選項。
答案3
您的堆資料段大小是多少-Xms2048m -Xmx3072m
。
您的資料段大小應與您的最大堆大小相對應(在本例中為 3072m)。因此,您的資料段大小應至少設定為3221225472
(以位元組為單位 3*1024*1024*1024 = 3GB)