2019年5月5日
一般的には、オブジェクトを生成する回数を減らし、必要なくなったらすぐに廃棄すべきというルールがある。一方、同じ種類のオブジェクトをなんども生成するのは全体としてのパフォーマンスの悪化に繋がります。このようなオブジェクトを破棄せずに再利用するようにすれば、パフォーマンスは大きく向上します。
どの型のオブジェクトが多くのメモリを消費しているかという点について、分析が必要です。このための最も簡単な方法が、ヒープヒストグラムを利用するというものです。ヒープヒストグラムを使えば、アプリケーション内で使われているオブジェクトの数を手早く確認できます。 ヒープヒストグラムのデータはとても小さいので、自動化されたテストの中で毎回出力されるようにするとよいでしょう。
ヒープヒストグラムよりも詳細な分析が必要な場合には、ヒープダンプが必要になります。 ヒープの分析では、まず保持メモリ量(retained memory)について調べるのが一般的です。保持メモリ量とは、該当するオブジェクトがガーベジコレクションの対象になった場合に解放されるメモリ量を表します。 ヒープの中で保持メモリ量の多いオブジェクトはドミネータ(dominator)と呼ばれます。 一般的な指針としては、コレクションのエントリではなくコレクション自体のオブジェクトから探索を初めて、最大のコレクションを探すようにしましょう。
OutOfMemoryErrorは次のような状況で発生します。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
このエラーが発生するのは、主にヒープメモリの不足が原因です。単に、使用中のオブジェクトが多すぎてヒープに収まらなくなったか、メモリリークが発生している可能性があるかのどちらかが考えられます。
どちらの場合でも、どのオブジェクトがメモリを最も多く消費しているかを知るにはヒープダンプの分析が必要です。[ヒープダンプの自動取得]
OutOfMemoryErrorの発生は予測ができないため、いつヒープダンプを取得するべきか判断するのは困難です。そこで、JVMには次のようなフラグが用意されています。
-XX:+HeapDumpOnOutOfMemoryError
OutOfMemoryErrorの発生時にヒープダンプを生成
-XX:HeapDumpPath=パス
ヒープダンプの出力先を指定
-XX:+HeapDumpAfterFullGC
フルガベージコレクションの後にヒープダンプを生成
-XX:+HeapDumpBeforeFullGC
フルガベージコレクションの前にヒープダンプを生成
アプリケーションはオブジェクトを追加するだけで解放はしないため、コレクションは、メモリリークを最も発生しやすいです。不必要になったオブジェクトは積極的にコレクションから削除しましょう。
Javaでメモリを効率的に利用するには、まずヒープメモリの使用量を減らすべきです。ここでは、メモリの使用量を減らすための3つの方法(オブジェクトトのサイズを減らす、オブジェクトの初期化を遅らせる、canonicalオブジェクトの利用)を紹介します。
オブジェクトはヒープ上の一定の領域を消費するので、メモリの使用量を減らすにはオブジェクトを小さくするのが一番の近道です。 オブジェクトのサイズを減らすには、インスタンス変数の数を減らすという方法とインスタンス変数のサイズを減らすという方法があります。nullのインスタンス変数も、一定のメモリを消費します。