現象

Java アプリケーション実行速度が低下し、最終的にはメモリ不足になるか、ログまたはコンソール出力に OutOfMemoryError:Java ヒープスペースOutOfMemoryError:gc オーバーヘッド限度の超過などのエラーが表示されます。

原因

このような問題は、以下の原因が考えられます。

考えられる原因として、java アプリケーション(この場合、CRX / CQ)が、Java のデフォルトのヒープメモリ設定を使用したコマンドラインから開始されたためと考えられます。つまり、jvm パラメーター -Xmx が指定されていません。CRX または CQ には、少なくとも256 MB のヒープが割り当てられている必要があります。この問題が発生した場合は、コマンドラインから始めて、ヒープメモリ設定が設定されていることを確認してください。次に例を示します。

java -Xmx512m -jar *.jar

これが当てはまらない場合、アプリケーションが余りにも多くのオブジェクトを、ガベージコレクションにリリースせずに保持している可能性があります。これはメモリリークを呼び出します。詳細はここを参照ください。Java アプリケーションでメモリの問題を分析する方法については、以下のセクションを参照してください。

分析、ソリューション

ヒープダンプの作成

ヒープダンプの自動生成

メモリ不足が発生した際に自動的にヒープダンプを作成するには、JVM パラメーター -XX:+HeapDumpOnOutOfMemoryError を追加します。すると、アプリケーションで OutOfMemoryError が発生したときにヒープダンプが自動的に生成されます。次に例を示します。

java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar

これにより、java プロセスのメモリが不足するたびに、プロセスのワーキングディレクトリにヒープダンプファイル(java_...hprof)が生成されます。このプロセスは、ヒープダンプが生成された後でも引き続き実行できます。通常、一つのヒープダンプファイルで問題は分析できます。

注意: CRX インスタンスを開始するために crx-quickstart/server/start スクリプトを使用している場合は、-XX:+HeapDumpOnOutOfMemoryErrorCQ_JVM_OPTS 変数に追加できます(変数にもコメントが付いていないことを確認ください)。例:

CQ_JVM_OPTS='-XX:+HeapDumpOnOutOfMemoryError'

このパラメーターを追加して CRX インスタンスを再起動した後、新しい jvm オプションが設定されていることを確認します。コマンドラインから ps -ef | grep java を実行してください。次に、-XX:+HeapDumpOnOutOfMemoryError が CRX Java プロセスのパラメーターとして表示されているかどうかを確認します。

ディスク容量の制限などの理由で、ヒープダンプを生成する異なるディレクトリを指定する必要がある場合は、-XX:HeapDumpPath=/path/to/generate/heapdump パラメーターを追加し、jvm にどこにファイルを置くかを指示することができます。

デバッグ関連の JVM パラメーターの使用方法についてはここを参照してください。

ヒープダンプの手動生成

Sun//Oracle JVM

手動でヒープダンプを生成するには、このコマンドを実行します(jmap および jps は、jdk ホームディレクトリの bin にあります)。

  1. ヒープダンプを生成する java プロセスの pid を調べます。
    • Unix または Linux では、ps -ef | grep java または jps -l で実行できます。
    • Windows の場合は、タスクマネージャーを開き、Ctrl+Shift+Esc を押してから、「表示列の選択PID(Process Identifier)」または「jps -l」へ移動します。
  2. 以下の jmap コマンドを実行し、/path/to/generate/heapdumpfile.hprof をヒープダンプファイルを生成したい場所に置き換え、1234 を前の手順で調べた pid に置き換えます。
    jmap -dump:format=b,file=/path/to/generate/heapdumpfile.hprof 1234
    

IBM JVM

まず、ダンプエージェントに関するデフォルトの JVM 設定を変更して、ユーザーシグナルの正しいダンプを生成する必要があります。ダンプにはいくつかの種類がありますが、完全なメモリ分析をおこなうには一般的に全体のシステムダンプが必要となります。以下の引数を追加:

Xdump:heap:opts=PHD+CLASSIC:events=user -Xdump:system:events=user

この「ユーザー」イベントは、JVM がオペレーティングシステムから SIGQUIT(Linux、AIX®、z /OS®、および i5 / OS™)または SIGBREAK(Windows)信号を受け取ったときに発生します。

詳細については、ここのベンダーのドキュメントを参照ください。

警告:ヒープダンプファイルは大きく、ディスク上の最大ヒープである -Xmx jvm パラメーター設定と同じサイズにすることができます。ダンプファイルが生成されるディレクトリに十分なディスク容量が割り当てられていることを確認してください。

ヒープダンプの分析

ヒープダンプを分析する良いツールは、EclipseMAT(Eclipse Memory Analyzer)です:http://www.eclipse.org/mat/

このツールは、IBM JVM が生成したダンプを分析できません。これらは、複数の可能性があります。IBM HeapAnalyzer は、PHD またはクラシックフォーマットのヒープダンプに対してうまく機能します。

完全なシステムダンプ分析を行うには、IBM Monitoring and Diagnostic Tools for Java - Memory Analyzer バージョン 1.2 をインストールした IBM Support Assistant Workbench を使用してください。

ヒープヒストグラム

ヒープヒストグラムは、Java クラスごとに使用されるライブオブジェクトとメモリ数の単純な測定値です。Java インストールによっては、必要なツールが使用できない場合や、常に動作しない場合があります。ヒストグラムを作成するには、まず Java プロセスのプロセス ID が必要です。これを取得するには、ps を実行、または(使用可能な場合)以下を実行します:

jps -l

この Java ツールは、実行中のすべての Java プロセスのプロセス ID を取得します。次に例を示します。

327 3332 sun.tools.jps.Jps 3313 crx-quickstart-....jar

次のコマンドを実行します。

jmap -histo 3313

リストは、必要なメモリの合計(シャロー:参照されているオブジェクトを除いたもの)でソートされます。出力の最初の 20 行が最も興味深いレベルのアイテムです。出力の例:

JVM バージョンは、1.5.0_20-141 です。ヒープを反復します。これは時間がかかる場合があります... 警告:スレッドの無効 TLAB をスキップしています t@62211 警告:スレッドの無効 TLAB をスキップしています t@62467 ... 要素数クラス詳細 ------------------------------------------------------- 10592904 12916 byte[] 10285840 75255 * ConstMethodKlass 6283176 58388 char[] 6042304 14928 int[] 4995752 116201 * SymbolKlass 4220896 75255 * MethodKlass 4196512 6969 * ConstantPoolKlass 2928560 6969 * InstanceKlassKlass 2631008 6066 * ConstantPoolCacheKlass 2395872 149742 org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId 1476008 7003 java.util.HashMap$Entry[] 1396128 58172 java.lang.String 1070232 44593 java.util.HashMap$Entry 753984 10036 short[] 735464 54 org.apache.jackrabbit.core.query.lucene.DocId[] 720192 7502 java.lang.Class 640704 13348 com.day.crx.persistence.tar.index.IndexEntry ...

追加情報

問題を分析するには、次の情報も必要:

  • インストールされているすべてのホットフィックスバージョン番号のリストを含む、CRX または CQ バージョン。
  • オペレーティングシステム、JVM ベンダー、およびバージョン。

参考文献

[1] http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/memleaks.html
[2] http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

本作品は Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License によってライセンス許可を受けています。  Twitter™ および Facebook の投稿には、Creative Commons の規約内容は適用されません。

法律上の注意   |   プライバシーポリシー