Java プロセスは、基本的に 2 つの異なるヒープ スペースで構成されます。
- Java ヒープ (新しい、古い、perm スペース)
- いわゆるネイティブ C ヒープ
上記は、OutOfMemory エラーや割り当ての失敗に関しては混乱を招くことがよくあります。特に 32 ビット モードでは、OS に応じて全体のプロセス空間が 4GB または 2GB に制限されます。
前述のように、32 ビット モードでの合計プロセス サイズは最大 4GB に制限されています。 Java ヒープと C ヒープの組み合わせ、およびその他のスペース。ライブラリ、スレッドなどの場合、この 4 GB の制限を超えることはできません。したがって、Java ヒープを増やすと、たとえば-Xmx/-Xms を 1.5gb から 2.5gb に増やすと、C ヒープに重大な副作用が生じます。増加する前は、C ヒープは簡単に 2GB まで大きくなる可能性がありました。 4GB -1.5GB =2.5GB 残っていたので。 Java ヒープを 1.5gb から 2.5gb に増やした後、他のすべてのスペース用に 4gb – 2.5gb =1.5gb しか残っていません。 C ヒープを含みます。
残念ながら、Java ヒープと C ヒープの大きさは完全にアプリケーションに依存します。 Java ヒープのサイズは明示的に構成できますが、これは C ヒープに対して行うことはできません。 C ヒープは、プロセス サイズが 4 GB の制限に達するまで単純に拡張されます。したがって、Java ヒープを大きすぎるように構成する場合は注意が必要です。これにより、C ヒープの割り当てエラーが発生する可能性があります。例えば。このようなメッセージは通常、C ヒープが使い果たされたことを意味します:
java.lang.OutOfMemoryError: requested 67108872 bytes for Chunk::new. Out of swap space?
コロンが 2 つある C++ 構文に注意してください。またはこれ:
# There is insufficient memory for the Java Runtime Environment to continue. # Native memory allocation (malloc) failed to allocate 65544 bytes
どちらの場合も、C ヒープが小さすぎました。解決策は、Java ヒープを減らすことでした。はい、減らすために!これにより、C ヒープが拡張する余地が増えました。一方で、従来の Java.lang.OutOfMemoryErrors にヒットする可能性もあります。これらは Java ヒープ容量が不十分であることを明確に示しています。
ご覧のとおり、32 ビット モードで操作すると、Java と C ヒープの間に競合が発生する可能性があり、解決が容易ではない可能性があります。すべてが失敗した場合は、64 ビットへの移行を検討してください。4 GB のプロセス サイズ制限はもはや問題ではありません。背景情報:Hotspot Java 仮想マシン (JVM) 自体は C++ で作成されています。したがって、すべての JVM 内部割り当ては C ヒープのみで行われます。たとえば、GC が起動して Java ヒープ内のデッド オブジェクトを収集する場合、GC はネイティブ ヒープ内の領域を割り当てて作業を実行します。
一方、Java プログラムによって割り当てられているすべての Java オブジェクトは、最終的に Java ヒープになります。 C ヒープは変更されません。