本節では、OutOfMemoryErrorがスローされた場合、考えられる原因とその対処方法を説明します。
なお、OutOfMemoryErrorがスローされた場合に出力されるメッセージ情報については、“8.6.1.1 メモリ領域不足事象発生時のメッセージ出力機能の強化”も参照してください。
想定される原因(メモリリーク)
VMがガーベジコレクションを繰り返しても、時間の経緯とともにメモリ消費量が増大していく場合、プログラム中メモリリークを起こしている可能性があります。
メモリリークの結果、Javaのヒープ不足が発生しOutOfMemoryErrorがスローされる場合があります。
この場合、ガーベジコレクションのログを採取して、Javaヒープの消費状況を確認してください。ガーベジコレクションのログを採取する方法は、“8.2.6 ガーベジコレクションのログ出力”を参照してください。
想定される原因(Javaヒープ不足)
通常、OutOfMemoryErrorは、Javaヒープ不足が原因でスローされます。
ガーベジコレクションのログを採取して、Javaヒープの消費状況を確認してください。
Javaヒープの空き容量がないことが確認されたら、Javaヒープをチューニングしてください。
ガーベジコレクションのログを採取する方法は、“8.2.6 ガーベジコレクションのログ出力”を参照してください。
Javaヒープのチューニング方法は、“8.4.1 Javaヒープのチューニング”を参照してください。
想定される原因(ユーザ空間不足)
多量のスレッドを生成して、多量のスタックがユーザ空間内に割り当てられ、ユーザ空間不足になった場合、次のOutOfMemoryErrorがスローされる、あるいはエラーメッセージとして表示を行いプロセスが終了します。
java.lang.OutOfMemoryError: unable to create new native thread |
また、JavaヒープやOSの仮想メモリに余裕があるにもかかわらず、ユーザ空間内にメモリを確保できなかった場合、次のOutOfMemoryErrorが出力されプログラムが終了します。
java.lang.OutOfMemoryError: requested サイズ bytes 制御名. Out of swap space? |
サイズ: | 確保できなかったメモリの大きさ |
制御名: | メモリが確保できなかったJava VMの制御名(該当情報がある場合にだけ表示) |
ユーザ空間が不足している場合は、Javaヒープまたはスタックのサイズを小さくするなどのチューニングを行ってください。
スタックのサイズをチューニングする方法は、“8.4.2 スタックのチューニング”を参照してください。
Javaヒープのチューニング方法は、“8.4.1 Javaヒープのチューニング”を参照してください。
なお、仮想メモリに余裕がある場合は、Javaプロセスを複数起動して、プロセス多重度を上げる方法もあります。J2EEアプリケーションまたはJavaEEアプリケーションの場合、J2EEまたはJavaEEのチューニングを行ってください。J2EEまたはJavaEEのチューニング方法の詳細は、それぞれのマニュアルを参照してください。
想定される原因(仮想メモリ不足)
仮想メモリが不足してスレッドが生成できない場合、次のOutOfMemoryErrorがスローされる、あるいはエラーメッセージとして表示を行いプロセスが終了します。
java.lang.OutOfMemoryError: unable to create new native thread |
また、OSの仮想メモリが不足した場合、次のOutOfMemoryErrorが出力されプログラムが終了します。
java.lang.OutOfMemoryError: requested サイズ bytes 制御名. Out of swap space? |
サイズ: | 確保できなかったメモリの大きさ |
制御名: | メモリが確保できなかったJava VMの制御名(該当情報がある場合にだけ表示) |
仮想メモリが不足した場合は、他の不要なプロセスを終了して仮想メモリに余裕を持たせるか、物理メモリ(RAM)またはスワップファイルを拡張して仮想メモリを増やすようにチューニングを行ってください。
想定される原因(ガーベジコレクション処理の実行抑止)
ガーベジコレクション処理(GC処理)の実行抑止により、クリティカルセクション状態時にOutOfMemoryErrorがスローされた場合は、必要に応じて、GC処理の実行抑止による影響ができるだけ小さくなるように、実行するアプリケーションの処理内容を見直してください(アプリケーション処理内の、GC処理の実行抑止に関係する機能の利用見直しを行ってください)。
GC処理の実行抑止については、“8.2.1 FJVMでサポートされるガーベジコレクション処理”を参照してください。
なお、Javaヒープのチューニングにより、GC処理の実行抑止によるOutOfMemoryErrorの発生が緩和できる場合があります。
クリティカルセクション状態時に、ネイティブプログラムからJNIを利用してJavaのオブジェクトの生成要求を行っていないアプリケーションの場合は、Old世代領域を大きくする(メモリ割り当てプール全体を大きくする)チューニングで、GC処理の実行抑止によるOutOfMemoryErrorの発生が緩和できる場合があります。
クリティカルセクション状態時に、ネイティブプログラムからJNIを利用してJavaのオブジェクトの生成要求を行っているアプリケーションの場合は、New世代領域を大きくするチューニングで、GC処理の実行抑止によるOutOfMemoryErrorの発生が緩和できる場合があります。
ガーベジコレクションのログを採取する方法は、“8.2.6 ガーベジコレクションのログ出力”を参照してください。
Javaヒープのチューニング方法は、“8.4.1 Javaヒープのチューニング”を参照してください。
GC処理の実行抑止により、クリティカルセクション状態でOutOfMemoryErrorがスローされたかどうかは、“メモリ領域不足事象発生時のメッセージ出力機能の強化”で出力されるメッセージを参照して判断してください。
また、EXTP4435メッセージまたはISJEE_OM1018メッセージが出力されている場合は、IJServerのコンテナ情報ログ(info.log)およびIJServerクラスタのJava VMログ(jvm.log)に出力される「Java VMのヒープ域不足の詳細情報」を参照して判断してください。
FJVMでは、メモリ領域不足事象発生時に出力されるメッセージ情報の強化を行なっています。
これによりFJVMでは、メモリ領域不足事象が発生した場合に、java.lang.OutOfMemoryErrorの例外メッセージ情報に加え、不足した領域の種別情報を図1の形式で出力します。
図1 メモリ領域不足事象が発生した場合に出力される不足した領域の種別情報
The memory was exhausted area_name |
area_name: | メモリ領域不足事象が発生した領域の名前や領域不足となったオブジェクトの要求サイズ(不足領域情報)を表示します。
|
heap_size: | メモリ領域不足事象が発生した際に使用中となっているメモリ割り当てプールのサイズ(単位:byte)。 |
max_heap_size: | 利用可能なメモリ割り当てプールの最大サイズ(単位:byte)。 |
perm_size: | メモリ領域不足事象が発生した際に使用中となっているPermanent世代領域のサイズ(単位:byte)。 |
max_perm_size: | 利用可能なPermanent世代領域の最大サイズ(単位:byte)。 |
メモリ領域不足事象が発生した際に出力される各領域の使用中サイズ(heap_size、perm_size)には、メモリ領域不足の原因となったオブジェクトの大きさは含まれません。
そのため巨大サイズのオブジェクト生成要求などによりメモリ領域不足事象が発生した場合には、「最大サイズ」と「使用中サイズ」の差が大きい場合(空き領域がたくさんあるように見える場合)がありますので注意してください。
NewGC処理では、New世代領域を「eden space」、「from space」および「to space」の3つの内部領域に細分割し、当該領域上において、一般に世代別GC制御と言われる制御方法を用いて、Javaアプリケーションが生成要求したオブジェクトを管理・制御しています。
このうち、「from space」および「to space」は、Java VMがNewGC処理を行う際の作業域的な役割を持つ領域となっています。そのため、「from space」および「to space」の各領域が占める大きさのうち、Javaアプリケーションからのオブジェクト生成要求のために使用される大きさは、その領域の一部分だけとなります。
そのため、出力データにおいて、メモリ割り当てプールやNew世代領域に空きがあるように見える場合であっても、実際には空きがない場合がありますので注意してください(空きがあるように見える場合であっても、その差は、NewGC処理用の作業域的な役割で使用済となっている場合があります)。
メモリ割り当てプールに対してメモリ領域不足事象が発生した場合に出力されるheap_sizeの値は、New世代領域での使用中サイズとOld世代領域での使用中サイズの合計値です。
New世代領域とOld世代領域は別々のオブジェクト格納域として管理・制御されますから、max_heap_sizeとheap_sizeの差の大きさが、そのまま生成要求できるオブジェクトの最大サイズにはなりませんので注意してください。
図2 メモリ領域不足事象が発生した場合に出力されるメッセージ出力例
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space |
図2の出力例の場合、4016バイトのオブジェクト生成要求において、メモリ割り当てプールに対してメモリ領域不足が発生したことを確認することができます。