JVMのメモリ不足の原因
質問は、Oracle HotspotJDK8に基づいています。
アプリケーションがjava.lang.OutOfMemory: Java heap space
例外に遭遇したとき、2つの考えられる理由があると思います。
- 割り当てられたJVMヒープサイズが
-Xmx
指定されたサイズに達し、GCシステムが十分なスペースを絞り出すことができません。 - 割り当てられたJVMヒープは到達しませんが
-Xmx
、JVMヒープを拡張するのに十分な物理メモリがありません。-Xms
<と仮定し-Xmx
ます。
1
JVMがjava.lang.OutOfMemory: Java heap space
例外をスローする理由はわかっています。ある2
合理的な原因の一つは?
言及されている記事をいくつか見つけましたjava.lang.OutOfMemoryError: native memory exhausted
が、それらはすべてIBMWebサイトに限定されています。このエクスペディションはIBMが実装したJVMに限定されていますか、それともJVM仕様の標準エクスペディションですか?
@Eugeneから提供されたコードを使っていくつかの実験を行いました。@Holgerが指摘したように、結果は環境によって異なります。私は、CentOSx64とWin7x64の両方で、Hotspot JDK8x64を使用してテストしました。簡単にするために、スワップと仮想メモリは無効になっています。
メモリバウンド(-Xmxおよび-Xms)を段階的に増やします。
I. -Xmx <使用可能なロジックメモリ
- CentOSとWindowsの両方で、OutOfMemoryError:Javaヒープスペースが表示されます
II。使用可能なロジックメモリ<-Xmx <最大物理メモリ
- CentOS:GCは、割り当ての失敗を使用して、GCのサーバー時間をフルに試行し、プロセスがシステムによって強制終了され、メッセージKilledが残ります。
- Windows:GCは、割り当ての失敗でGCサーバー時間をフルにしようとし、OutOfMemoryError:Javaヒープスペースをスローします。
III。-Xmx>最大物理メモリ
- CentOS:IIと同じ
- Windows:IIと同じ
IV。-Xms>最大物理メモリ
- CentOS:JVMが起動しないようです。エラーメッセージは次のようなものです。
Java HotSpot(TM)64ビットサーバーVM警告:情報:os :: commit_memory(0x00000000e62a0000、349569024、0)が失敗しました。error = 'メモリを割り当てることができません'(errno = 12)
- Windows:JVMを起動できませんでした。エラーメッセージは次のようなものです。
VMの初期化中にエラーが発生しましたオブジェクトヒープ用に十分なスペースを予約できませんでした
そのため、同じJVMはOSによって動作が異なります。
- Windowsでは、OSはJVMを強制終了しません。また、JVMは、メモリ使用量が増加すると、常にOutOfMemoryError:Javaヒープスペースをスローします。
- Linuxでは、十分なメモリがない場合、OSはプロセスを強制終了します。
- 両方のOSで、使用可能なメモリがJVMの最小要件を満たしていない場合、JVMを起動できませんでした。
回答
まず第一に、あなたの質問の下のコメントが説明しているように、GCが「メモリ不足」で失敗する理由は他にもあります。
ポイント番号(2)の証明は簡単で、常に割り当てるコードを作成するだけです。
public static void main(String[] args) {
test(1);
}
static void test(int x){
List<byte[]> list = new ArrayList<>();
while(x == 1){
byte [] b =new byte[1 * 1024 * 1024];
b[100] = 42;
list.add(b);
}
System.out.println(list.hashCode());
}
そして、RAM-Xms1g -Xmx100g
が少ないシステムで、を使用してこれを実行し100g
ます。GCログを有効にして("-Xlog:heap*=debug" "-Xlog:gc*=debug"
たとえば、java-9フラグで行った)、GCがこの一定の割り当てに対処しようとして、最終的に失敗することを確認できます。