Java Platform, Standard Editionトラブルシューティング・ガイド
目次      

3.1 Javaフライト・レコーダによるメモリー・リークのデバッグ

Java Flight Recorder (JFR)は商用機能です。 開発者のデスクトップまたはラップトップ上では無償で、また評価目的であればテスト環境、開発環境および本番環境で使用できます。 ただし、JFRを本番サーバーで有効にする場合は、商用ライセンスが必要です それ以外の目的でJava Mission Control (JMC)をJDKで使用する場合、商用ライセンスは必要ではありません JFRの商用機能および可用性の詳細は、「Oracle Java SEサブスクリプション」を参照してください。

フライト記録の作成の詳細は、「フライト記録の作成方法」を参照してください。

次の項では、図を示して、Javaフライト・レコーダでメモリー・リークをデバッグする方法を説明します。

3.1.1 メモリー・リークの検出

スロー・メモリー・リークの検出は難しい場合があります。 一般的な症状は、頻繁なガベージ・コレクションにより実行に時間がかかり、その後、アプリケーションが低速になります。 やがてOutOfmemoryErrorsが表示される可能性があります。 ただし、Javaフライト・レコーダを使用すると、問題が発生する前であっても、メモリー・リークを早期に検出できます。

アプリケーションのライブ・セットの経時的な増加がないか確認します。 ライブ・セットは、Oldコレクションの後(すべての非ライブ・オブジェクトがガベージ・コレクトされた後)に使用されるJavaヒープ容量です。 ライブ・セットは、様々な方法で調査できます。たとえば、-verbosegcオプションを使用して実行するか、JMC JMXコンソールを使用してJVMに接続し、com.sun.management.GarbageCollectorAggregator MBeanを見ます。 しかし、別の簡単なアプローチは、フライト記録を取ることです。

記録を開始するときにヒープ統計を有効にすると、記録の開始時と終了時にOldコレクションがトリガーされます。 これにより、アプリケーションに若干の遅延が生じる場合があります。 しかし、ヒープ統計は、正確なライブ・セット情報を生成します。 やや急速なメモリー・リークが疑われる場合は、たとえば、1時間以上実行されるプロファイリング記録を取ります。 図3-1に示すように、「メモリー」タブをクリックし、「ガベージ・コレクション」タブを選択して、最初と最後のOldコレクションを確認します。

図3-1 メモリー・リークのデバッグ - 「ガベージ・コレクション」タブ

図3-1の説明が続きます
「図3-1 メモリー・リークのデバッグ - 「ガベージ・コレクション」タブ」の説明

図3-1に示すように、最初のOldコレクションを選択して、GC後のヒープ・データとヒープ使用量を調べます。 この記録では、34.10MBです。 今度は、最後のOldコレクションからの同じデータを調べて、ライブ・セットが増加したかどうかを確認します。 記録を取る前に、アプリケーションが起動し、安定した状態に到達できるようにする必要があります。

ゆっくりしたリークの場合は、5分間の短時間の記録を取ることができます。 次に、たとえば、(メモリー・リークの速さに応じて)24時間後に、もう一度記録を取ります。 明らかに、ライブ・セットは上下しますが、時間の経過とともに着実に増加している場合は、メモリー・リークの可能性があります。

3.1.2 リーク・クラスの調査

リークを示す記録を取った後、「オブジェクト統計」を調べます。 1つの長い記録を検討し、記録を通してヒープ使用量が最も増加したクラスを調べます。 間隔を置いて複数の記録を取った場合は、図3-2に示すように、「ヒープの内容」セクションを比較し、記録間で最も増加しているオブジェクト・タイプを調べます。

図3-2 メモリー・リークのデバッグ - リーク・クラスの調査

図3-2の説明が続きます
「図3-2 メモリー・リークのデバッグ - リーク・クラスの調査」の説明

特に、標準ライブラリの一部ではないクラスに注目してください。 たとえば、多くの場合、最大の増加率の1つとしてChar配列が表示されます。 これは、多くのStringsが割り当てられているためです。したがって、これらのStringsを維持しているオブジェクトに注意します。 10個のStringsをメンバーとして持つクラスがある場合、オブジェクト自体がヒープを使いすぎることはありません。 ヒープは、主にChar配列へのポインタが含まれているStringsによって使用されます。 したがって、オブジェクトのサイズではなく、インスタンスの数でソートするのが適切です。 いずれかのアプリケーション・クラスに多くのインスタンスがある場合、それらのオブジェクトが他のオブジェクトを維持している可能性があります。

3.1.3 リークの調査

実際のリークを見つけることは困難な場合があります。この時点で実行することの1つは、HPROFをダンプし、疑わしいオブジェクトがどのように維持されているかを調べるためにjhatユーティリティを使用してJavaヒープを検査することです。 また、JMCプラグインのJOverflowを使用して、HPROFダンプの参照チェーンを調べることもできます。

フライト記録を使用して、いくつかの追加情報を得ることができます。

図3-3に示すように、「割当て」サブタブで、オブジェクトの割当先のサンプルを見ます。

図3-3 メモリー・リークのデバッグ - 「割当て」タブ

図3-3の説明が続きます
「図3-3 メモリー・リークのデバッグ - 「割当て」タブ」の説明

特定のクラスのリークが予想される場合は、「新しいTLABの割当て」タブを見てください。 割り当てられているクラス・サンプルをチェックします。 スロー・リークの場合は、このオブジェクトの割当てが少なく、サンプルがないこともあります。 また、特定の割当てサイトのみがリークの原因となっている可能性もあります。 要約すると、これによってリークの適切な割当てスタック・トレースに到達することは保証されませんが、重要な手がかりを得る可能性があります。

目次      

Copyright © 1993, 2025, Oracle and/or its affiliates. All rights reserved.