Java VMのメモリ不足――原因切り分けから解決まで:Java Review(1/2 ページ)
Java VMのメモリ不足の問題は、解決までに時間を要する。だが適切な初期調査を行えば、ある程度まで原因を絞り込め、早期解決につながる。今回はメモリ不足問題の対応方法を、体系立てて解説する。
問題解決のポイント
Java VMでメモリ不足が発生した時に重要となるポイントは、早期に発生個所の特定と原因の切り分けである。
Webシステムでメモリが不足すると、「java.lang.OutOfMemoryError」メッセージが出力される。このメッセージが出力された時、最初に行うことは、WebサーバやJava VMのログを確認することだ。これらのログから障害の痕跡を発見できると、障害内容からメモリ不足の原因を切り分けられる。しかし、使用しているJava VMによっては、障害の切り分けに必要な情報が得られない場合もある。その場合、GCログが障害解析の資料として役に立つ。
以降、Webシステムを例に、不足しているメモリ域の判別方法、メモリ不足の原因による切り分けと対処方法について説明する。
初期調査――不足しているメモリ域を判別しよう
GCログには、GC前後のメモリ使用量の情報が残されているため、Java VMが管理するメモリ域の使用状況の推移を把握できる。GCログの情報を追いかけることで、どのメモリ域が不足しているかを把握できるのだ。ただ、GCログにはJava VMが管理するメモリ域の情報しか出力されない。メモリ域を判別するには、GCログの情報からJava VMが管理するメモリ域に関する問題を読み取れるか否かが、ポイントとなる。
例えば、GCログの事象から、不足したメモリ域を把握できる。以下に表で示す。
例 | 事象 | 考えられる原因 |
---|---|---|
1 | ある特定の時間帯にJavaヒープのメモリ使用量が急速に増加し、GCが多発している | Javaヒープでメモリ不足が発生していることが考えられる |
2 | GCログにオプションを指定して詳細情報を出力してみたところ、Permヒープの使用量がほぼ最大値になっており、Full GCが繰り返し発生している | Permヒープでメモリ不足が発生していることが考えられる |
3 | JavaヒープやPermヒープに問題がないにもかかわらず、「OutOfMemoryError」が発生している | Cヒープのメモリ不足が考えられる |
具体的な調査――メモリ不足の原因の把握と対処方法を理解しよう
次にメモリ不足の原因を把握しよう。メモリ不足の原因には、設定ミスなどによりメモリが確保できない場合や、業務プログラムなどに問題がありメモリリークを引き起こしている場合などがある。GCログなどの資料をもとに、メモリ不足の原因を把握しよう。次の表に、メモリ不足時の代表的な現象とその原因を示す。
表に示したように、JavaヒープやPermヒープが不足している場合には、GCログのメモリ増加傾向が判断材料となる。例えば、長時間Webシステムを運用している時に、Full GCが起きてもメモリ使用量が増加傾向にあれば、まずはメモリリークを疑ってみる。
一方、Cヒープが不足している場合は、スレッド数を確認する。スレッド数が多い場合には、Cヒープが枯渇する可能性がある。また、別の要因として、最大スレッド数を設定するカーネルパラメータが妥当でないためにスレッドが作られなくなる場合もあるので、OSの設定も確認する。
ここまでで、原因を特定できる。では次に、原因ごとの対処方法について見ていこう。設定ミスでメモリが不足している場合は、設定を見直して正しい設定を行えばよい。その場合、メモリ域ごとに以下の個所を見直してみる。
メモリ域 | 見直す設定 |
---|---|
Javaヒープ | Javaヒープの最大サイズ(-Xmx)を確認する |
Permヒープ | Permヒープの最大サイズ(-XX:MaxPermSize)を確認する |
Cヒープ | Webサーバに設定した最大同時実行数を見直す(多重度が多すぎる可能性あり)、またはカーネルパラメータの設定値を見直す |
一方、これらの設定に問題がなく、メモリが不足している場合は、アプリケーションのバグやメモリリークが疑われる。
Javaヒープの場合、GCログを参照することで、どの時間帯でFull GCが多発しているか、またはメモリ使用量が増加し始めているかといった情報が得られる。これらの情報をもとに、問題となる処理を特定して対策する。手順の一例を紹介しよう。
順番 | 手順 |
---|---|
1 | GCログで問題となる時間帯(メモリサイズが増加した時間帯)を調査する |
2 | 「1」の結果を基に、Webサーバのログを参照して、メモリサイズが増加したときのリクエスト情報からURLを絞り込み、問題となる処理を特定する |
3 | 問題となる処理を実行し、メモリ不足が発生した状況を再現する |
4 | 再現時にプロファイラの情報やスレッドダンプを採取して、メモリサイズが増加していく傾向のあるクラスをピックアップする |
5 | 調査対象クラスの利用個所に対応するソースを検証し、問題を引き起こした原因を対策する |
なおWebシステムでは、一般的にCヒープが不足することは少ない。ただし、業務プログラム内でJNIを使用している場合に、Cヒープ不足が発生したときには、業務プログラムでの“Cヒープの解放漏れ”の可能性を疑ってみよう。なぜなら、JNIを使用する場合は、Javaと異なり、業務プログラム内で明示的にメモリを解放する必要があるからだ。業務プログラムのJNI使用個所を見直して、Cヒープが解放されているかを確認しよう。
Copyright © ITmedia, Inc. All Rights Reserved.