このエラーメッセージでコードがクラッシュする
Executing "/usr/bin/Java com.utils.BotFilter"
OpenJDK 64-Bit Server VM warning: INFO:
os::commit_memory(0x0000000357c80000, 2712666112, 0) failed;
error='Cannot allocate memory' (errno=12)
Java Runtime Environmentを続行するためのメモリが不足しています。ネイティブメモリ割り当て(malloc)は、予約メモリをコミットするための2712666112バイトの割り当てに失敗しました。/jvm-29955/hs_error.log`
生成されたhs_error.log file
:
クラッシュログからのこの行は私にとって興味深いようです:
Memory: 4k page, physical 98823196k(691424k free), swap 1048572k(0k free)
マシンにはメモリはあるが、スワップ領域が不足しているということですか?
クラッシュログのmeminfoはここにありますが、MemFreeとMemAvailableの違いなど、どのように解釈すればよいのかわかりません。このプロセスはどのくらいのメモリを消費しますか?
/proc/meminfo
:
MemTotal: 98823196 kB
MemFree: 691424 kB
MemAvailable: 2204348 kB
Buffers: 145568 kB
Cached: 2799624 kB
SwapCached: 304368 kB
Active: 81524540 kB
Inactive: 14120408 kB
Active(anon): 80936988 kB
Inactive(anon): 13139448 kB
Active(file): 587552 kB
Inactive(file): 980960 kB
Unevictable: 0 kB
Mlocked: 0 kB
SwapTotal: 1048572 kB
SwapFree: 0 kB
Dirty: 1332 kB
Writeback: 0 kB
AnonPages: 92395828 kB
Mapped: 120980 kB
Shmem: 1376052 kB
Slab: 594476 kB
SReclaimable: 282296 kB
SUnreclaim: 312180 kB
KernelStack: 317648 kB
PageTables: 238412 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 50460168 kB
Committed_AS: 114163748 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 314408 kB
VmallocChunk: 34308158464 kB
HardwareCorrupted: 0 kB
AnonHugePages: 50071552 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 116924 kB
DirectMap2M: 5115904 kB
DirectMap1G: 95420416 kB
可能な解決策:
もう1つの可能性(たった今遭遇した)は、Linuxでの「メモリーのオーバーコミット」の設定が不適切であることです。
私の状況では、/proc/sys/vm/overcommit_memory
が "2"に設定され、/proc/sys/vm/overcommit_ratio
が "50"に設定されていました。
大量のメモリを使用できる可能性があるため、これは非常に誤解を招く問題です。しかし、割り当ては明らかに理由もなく失敗します。
現在、設定はデフォルトに変更できます(賢明な方法でオーバーコミット)(再起動まで):
echo 0 >/proc/sys/vm/overcommit_memory
...または永続的に:
echo "vm.overcommit_memory=0 >> /etc/sysctl.conf
sysctl -p /etc/sysctl.conf # apply it immediately
注:これは、/proc/meminfo
の出力を調べることでも部分的に診断できます。
...
CommitLimit: 45329388 kB
Committed_AS: 44818080 kB
...
質問の例では、Committed_AS
はCommitLimit
よりもはるかに高く、(割り当てが失敗するという事実とともに)オーバーコミットが有効になっていることを示していますが、ここでは両方の値が近く、つまり制限が厳密に実施されます。
これらの設定とその効果に関する優れた詳細な説明(およびそれらを変更する意味がある場合)は、この pivotal blog entry にあります。 (Tl; dr:オーバーコミットを使用することは、重要なプロセスでスワップを使用したくない場合に便利です)
Scary Wombat が言及しているように、JVMは2712666112バイト(2.7 Gb)のメモリを割り当てようとしていますが、691424000バイト(0.69 Gb)の空き物理メモリしかなく、スワップで利用できるものはありません。