Javaでサーバアプリケーションを開発している場合に遭遇する問題に「Out Of Memory」がある。Javaアプリケーションが使用するメモリが増え続け、最終的に許容範囲を超えてJava仮想マシンがクラッシュする。この問題に対するもっとも簡単な対処方法は、物理的にメモリの容量を増やしてJava仮想マシンが利用できるメモリ容量を引き上げること、もうひとつは、クラッシュする前に定期的にアプリケーションを再起動することだ。強引な方法だが、実効性のある方法でもある。しかし、根本的に原因を解決することにはならず、何らかの原因でいつかOut of Memoryが発生する危険性が存在しつづけることになる。

根本的に問題を解決したい場合には、どの部分でメモリリークが発生しているかを追跡し、対象部分のコードを書き換える必要がある。そうした場合に参考になる記事が「Fix Memory Leaks in Java Production Applications」として掲載された。実際にJavaアプリケーションで発生したメモリリークを追跡し、サードパーティ製のログライブラリに問題があることを突き止め解決した、というストーリーが紹介されている。メモリリークの追跡を簡単にまとめると次の通り。

Out Of Memoryを発生させメモリダンプを取得する

メモリダンプを解析して、どのオブジェクトがメモリ消費の原因になっているかを階層的にトレースする

疑わしいAPIやライブラリの動作に注目し、なぜメモリが解放されないのかを調査する

Javaにおけるメモリリークは、解放されるべき(解放されるものだとプログラマは信じている)オブジェクトが解放されずに保持され続けている状態を指す。プログラミング上はnullを代入することで参照を切り、ガベージコレクタに回収されやすくするというのがひとつの作法であり有効な対処方法だが、「Fix Memory Leaks in Java Production Applications」で紹介されているのはこれとは違うパターンのメモリリーク。

「Fix Memory Leaks in Java Production Applications」で明らかになったのは、高負荷のサーバにおいては不適切なログ機能を使ってしまったため、確保されたものの実質的には使われない状態でログデータを長時間に渡ってメモリ上に保持しつづけ、最終的にOut of Memoryを誘発していた、というものになっている。状況に対して不適切な方法や機能を使うことでOut of Memoryが発生するパターンとして参考になる。



続きを読む