OutOfMemoryErrorがスローされた場合、考えられる原因とその対処方法を説明します。
なお、OutOfMemoryErrorがスローされた場合に出力されるメッセージ情報については、“10.6.1.1 メモリ領域不足事象発生時のメッセージ出力機能の強化”も参照してください。
想定される原因(メモリリーク)
VMがガーベジコレクションを繰り返しても、時間の経緯とともにメモリ消費量が増大していく場合、プログラム中メモリリークを起こしている可能性があります。
メモリリークの結果、Javaのヒープ不足が発生しOutOfMemoryErrorがスローされる場合があります。
この場合、ガーベジコレクションのログを採取して、Javaヒープの消費状況を確認してください。ガーベジコレクションのログを採取する方法は、“10.2.6 ガーベジコレクションのログ出力”を参照してください。
想定される原因(Javaヒープ不足)
通常、OutOfMemoryErrorは、Javaヒープ不足が原因でスローされます。
ガーベジコレクションのログを採取して、Javaヒープの消費状況を確認してください。
Javaヒープの空き容量がないことが確認されたら、Javaヒープをチューニングしてください。
ガーベジコレクションのログを採取する方法は、“10.2.6 ガーベジコレクションのログ出力”を参照してください。
Javaヒープのチューニング方法は、“10.4.1 Javaヒープおよびメタスペースのチューニング”を参照してください。
想定される原因(メタスペース不足)
メタスペースが不足によって、OutOfMemoryErrorがスローされる場合があります。
ガーベジコレクションのログを採取して、メタスペースの消費状況を確認してください。
メタスペースの空き容量がないことが確認されたら、メタスペースをチューニングしてください。
ガーベジコレクションのログを採取する方法は、“10.2.6 ガーベジコレクションのログ出力”を参照してください。
メタスペースのチューニング方法は、“10.4.1 Javaヒープおよびメタスペースのチューニング”を参照してください。
注意
メタスペースは、クラスローダーごとに管理するため、あるクラスローダーでロードされたクラス情報を、別のクラスローダーが管理するメタスペースに格納できません。
また、各クラスローダーのメタスペースは、クラス情報ごとに取得するのではなく、ある程度のまとまったサイズごとに取得して、そこにクラス情報を設定していきます。
このため、取得済みのメタスペースに空きがある場合でも、別のクラスローダーが管理するものであれば、その空きを使用できません(使用済みと扱います)。
その結果、使用済みのサイズが“-XX:MaxMetaspaceSize”オプションで指定した値に到達していないにも関わらず、OutOfMemoryErrorがスローされる場合があります。
想定される原因(ユーザ空間不足)
多量のスレッドを生成して、多量のスタックがユーザ空間内に割り当てられ、ユーザ空間不足になった場合、次のOutOfMemoryErrorがスローされる、あるいはエラーメッセージとして表示を行いプロセスが終了します。
java.lang.OutOfMemoryError: unable to create new native thread |
ユーザ空間が不足している場合は、Javaヒープまたはスタックのサイズを小さくするなどのチューニングを行ってください。
スタックのサイズをチューニングする方法は、“10.4.2 スタックのチューニング”を参照してください。
Javaヒープおよびメタスペースのチューニング方法は、“10.4.1 Javaヒープおよびメタスペースのチューニング”を参照してください。
なお、仮想メモリに余裕がある場合は、Javaプロセスを複数起動して、プロセス多重度を上げる方法もあります。J2EEアプリケーションまたはJava EE 7 アプリケーションの場合、J2EEまたはJava EE 7のチューニングを行ってください。J2EEまたはJava EE 7のチューニング方法の詳細は、それぞれのマニュアルを参照してください。
想定される原因(仮想メモリ不足)
仮想メモリが不足してスレッドが生成できない場合、次のOutOfMemoryErrorがスローされる、あるいはエラーメッセージとして表示を行いプロセスが終了します。
java.lang.OutOfMemoryError: unable to create new native thread |
仮想メモリが不足した場合は、他の不要なプロセスを終了して仮想メモリに余裕を持たせるか、物理メモリ(RAM)またはスワップファイルを拡張して仮想メモリを増やすようにチューニングを行ってください。
想定される原因(ガーベジコレクション処理の実行抑止)
ガーベジコレクション処理(GC処理)の実行抑止により、クリティカルセクション状態時にOutOfMemoryErrorがスローされた場合は、必要に応じて、GC処理の実行抑止による影響ができるだけ小さくなるように、実行するアプリケーションの処理内容を見直してください(アプリケーション処理内の、GC処理の実行抑止に関係する機能の利用見直しを行ってください)。
GC処理の実行抑止については、“10.2.1 FJVMでサポートされるガーベジコレクション処理”を参照してください。
なお、Javaヒープのチューニングにより、GC処理の実行抑止によるOutOfMemoryErrorの発生が緩和できる場合があります。
クリティカルセクション状態時に、ネイティブプログラムからJNIを利用してJavaのオブジェクトの生成要求を行っていないアプリケーションの場合は、Old世代領域を大きくする(メモリ割り当てプール全体を大きくする)チューニングで、GC処理の実行抑止によるOutOfMemoryErrorの発生が緩和できる場合があります。
クリティカルセクション状態時に、ネイティブプログラムからJNIを利用してJavaのオブジェクトの生成要求を行っているアプリケーションの場合は、New世代領域を大きくするチューニングで、GC処理の実行抑止によるOutOfMemoryErrorの発生が緩和できる場合があります。
ガーベジコレクションのログを採取する方法は、“10.2.6 ガーベジコレクションのログ出力”を参照してください。
Javaヒープおよびメタスペースのチューニング方法は、“10.4.1 Javaヒープおよびメタスペースのチューニング”を参照してください。
注意
GC処理の実行抑止により、クリティカルセクション状態でOutOfMemoryErrorがスローされたかどうかは、“メモリ領域不足事象発生時のメッセージ出力機能の強化”で出力されるメッセージを参照して判断してください。
また、EXTP4435メッセージまたはPCMI1105メッセージが出力されている場合は、IJServerのコンテナ情報ログ(info.log)およびIJServerクラスタのJava VMログ(console.log)に出力される「Java VMのヒープ域不足の詳細情報」を参照して判断してください。
FJVMでは、メモリ領域不足事象発生時に出力されるメッセージ情報の強化を行っています。
これによりFJVMでは、メモリ領域不足事象が発生した場合に、java.lang.OutOfMemoryErrorの例外メッセージ情報に加え、不足した領域の種別情報を以下の形式で出力します。
メモリ領域不足事象が発生した場合に出力される不足した領域の種別情報
The memory was exhausted area_name Java heap size / max Java heap size = heap_size / max_heap_size Java metaspace size / max Java metaspace size = metaspace_size / max_metaspace_size
メモリ領域不足事象が発生した領域の名前や領域不足となったオブジェクトの要求サイズ(不足領域情報)を表示します。
不足領域情報としては以下の項目があります。
on Java heap space. : requested <NNNN> bytes
NNNNバイトのオブジェクト生成要求において、メモリ割り当てプール(New世代領域またはOld世代領域)に対してメモリ領域不足事象が発生した場合です。
なお、エルゴノミクス機能によるメモリ領域不足事象の検出機能が有効な場合で、かつ当該機能によりメモリ領域不足事象を検出した場合、この項目になる場合があります。
on Java heap space. : requested <NNNN> bytes (in critical section)
意味は「on Java heap space. : requested <NNNN> bytes」と同じですが、メモリ領域不足事象発生時、クリティカルセクション状態でGC処理の実行が抑止されていたことを示しています。
on Metaspace. : requested <NNNN> bytes
NNNNバイトのオブジェクト生成要求において、メタスペースに対してメモリ領域不足事象が発生した場合です。
on Metaspace. : requested <NNNN> bytes (in critical section)
意味は「on Metaspace. : requested <NNNN> bytes」と同じですが、メモリ領域不足事象発生時、クリティカルセクション状態でGC処理の実行が抑止されていたことを示しています。
(なし)
スタックやヒープなど、Javaヒープやメタスペース以外の領域に対してメモリ領域不足事象が発生した場合です。特にjava.lang.OutOfMemoryErrorの例外メッセージ情報が“java.lang.OutOfMemoryErrorがスローされた場合”の「ユーザ空間不足」または「仮想メモリ不足」の場合に出力される形式の場合は、スタックやヒープなど、Javaヒープやメタスペース以外の領域に対してメモリ領域不足事象が発生した場合と断定できます。
またはJavaアプリケーション実行時における配列生成式の評価の段階で、配列オブジェクトの長さ(配列要素の数)から、当該配列オブジェクトを割り当てるための領域が十分でないと評価された場合(配列の長さ(配列要素の数)が大きすぎ、配列オブジェクトとしての大きさが2ギガバイト程度もしくはそれ以上の大きさになる配列の定義がある場合)。
またはクラスのロード処理でメモリ不足が発生した場合。
なお、エルゴノミクス機能によるメモリ領域不足事象の検出機能が有効な場合で、かつ当該機能によりメモリ領域不足事象を検出した場合、この項目になる場合があります。
メモリ領域不足事象が発生した際に使用中となっているメモリ割り当てプールのサイズ(単位:byte)。
利用可能なメモリ割り当てプールの最大サイズ(単位:byte)。
メモリ領域不足事象が発生した際に使用中となっているメタスペースのサイズ(単位:byte)。
利用可能なメタスペースの最大サイズ(単位:byte)。
注意
メモリ領域不足事象が発生した際に出力される各領域の使用中サイズ(heap_size、metaspace_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の差の大きさが、そのまま生成要求できるオブジェクトの最大サイズにはなりませんので注意してください。
例
メモリ領域不足事象が発生した場合に出力されるメッセージ出力例
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space |
4016バイトのオブジェクト生成要求において、メモリ割り当てプールに対してメモリ領域不足が発生したことを確認することができます。