在記憶體受限的伺服器(如 1GB RAM VPS)執行 java -version 即報錯:
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007ff55c5ea000, 4096, 0) failed; error='Cannot allocate memory' (errno=12) # There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (mmap) failed to map 4096 bytes for committing reserved memory.
JVM 在啟動子進程(如 ProcessBuilder、JNI 呼叫系統指令)時,會先 fork() 複製父進程記憶體映射,再 exec() 載入新程式。Linux 預設採用 Strict Overcommit 策略:fork() 瞬間需要為子進程預留與父進程相同大小的虛擬記憶體,即使隨後 exec() 會釋放大部分頁面,峰值提交量仍可能超過物理記憶體+Swap 上限,導致 mmap 失敗。
修改 /proc/sys/vm/overcommit_memory 為 1(Always Overcommit),核心不再檢查可用記憶體直接允許分配。
echo 1 > /proc/sys/vm/overcommit_memory
# /etc/sysctl.conf vm.overcommit_memory = 1 # 執行 sysctl -p 或重啟生效
副作用:若惡意程式大量 malloc 卻不使用,可能觸發 OOM Killer 殺死隨機進程。生產環境建議同時配置 vm.overcommit_ratio 並監控記憶體水位。
JDK 9+ 已在 ProcessBuilder 內部嘗試使用 posix_spawn 避免 fork 記憶體翻倍。若受限於舊版 JDK,可採用:
--memory-swappiness=0 並給予足夠 --memory 配額。free -h 確認物理記憶體與 Swap 可用量;cat /proc/sys/vm/overcommit_memory 檢查當前策略(0=heuristic, 1=always, 2=strict);java -version 應無錯誤輸出;dmesg | grep -i oom 確無 OOM Killer 記錄。Documentation/vm/overcommit-accounting