JProfiler ヘルプ

ガベージコレクターの分析

ガベージコレクター(GC)のランタイム特性を理解し分析することは、いくつかの理由から重要です。第一に、GCの一時停止(ポーズ)はアプリケーションの応答性に直接影響を与える可能性があります。 ガベージコレクターの動作状況を理解することで、その設定を最適化してこれらの一時停止を短縮できます。 一般に、長時間のGCサイクルが頻繁に発生する場合、ヒープが小さすぎるか、一時オブジェクトが過剰に作成されている可能性があります。

ガベージコレクタープローブを使用すると、これらの問題を解決し、適切なガベージコレクターの選択、ヒープサイズ、その他のJVMパラメータなど、JVM設定をチューニングする際により適切な判断を下すことができます。

ガベージコレクタープローブは他のプローブとは異なるビューを持ち、異なるデータソースも使用します。 JVMのプロファイリングインターフェースからデータを取得するのではなく、JFRストリーミングを使用してJDK Flight RecorderからのGC関連イベントを分析します。 JFRイベントストリーミングに依存しているため、GCプローブはHotSpot JVM上のJava 17以降をプロファイルする場合にのみ利用可能です。 JFRスナップショットを開くと、使用されているJavaバージョンに関係なく、まったく同じプローブを利用できます。

ガベージコレクションビュー

ガベージコレクタープローブのメインビューは「Garbage collections」テーブルです。 記録されたすべてのガベージコレクションを行として表示し、最も重要なメトリクスを列として表示します。

「Cause」列には、ガベージコレクションがトリガーされた理由が表示されます。例えば、 System.gc()の呼び出しによってフルガベージコレクションがトリガーされた場合、 「Collector」列の対応する「G1Full」の値からそれを確認できます。また、これにより20 msという大幅な一時停止が発生しており、 一般的にSystem.gc()の呼び出しが推奨されない理由がわかります。その他の原因としては、Young世代領域のコレクション(「G1New」)や、 Old世代内の参照されていないオブジェクトをクリーンアップするG1コレクターの混合GCコレクション(「G1Old」)がトリガーされます。 Young世代のコレクションの方が多くのオブジェクトを回収するにもかかわらず、混合GCコレクションの方が一貫して時間がかかっていることが確認できます。

特別なGC処理を伴う回収された参照は、「final」、「weak」、「soft」、「phantom」参照として個別の列に表示されます。

最長の一時停止と一時停止の合計に別々の列が用意されている理由は、各ガベージコレクションが個別の休止を発生させる複数のフェーズで構成されているためです。 また、ガベージコレクションは実行中にJVMを部分的にしか一時停止させないため、ガベージコレクションの「Duration」は一時停止の合計とは一致しません。 スクリーンショットの「G1Old」コレクションでは、実行時間全体の約5分の1しか一時停止していないことがわかります。

ガベージコレクションのさまざまなフェーズを調査するには、「GC ID」列のツリーアイコンを切り替えます。

上のスクリーンショットでは、G1コレクターの混合GCコレクション(「G1Old」)が展開されています。 大半の時間がJVMを一時停止させない「Class Unloading」に費やされていることがわかります。 右側には、ガベージコレクションに関する詳細な統計情報が表示されています。 ここでは、使用ヒープ量は変化していませんが、使用メタスペース量は0.1%増加しています。

各コレクターのフェーズは異なります。上のスクリーンショットにはフルコレクションが表示されています。 ヒープ全体で生存オブジェクトをマークするのに多くの時間が費やされています。 コレクションの終了時、使用ヒープ量は15.7%削減されましたが、メタスペース量は変わりませんでした。

ガベージコレクションを分析する際、フィルタリングはガベージコレクションの異なるサブセットを比較するための重要なツールです。 テーブルの上部には、任意の列を選択して対応するフィルターを設定できるフィルターセレクターがあります。 類似したガベージコレクションを表示するより簡単な方法は、テーブルのコンテキストメニューを使用して、選択した行の列値に基づいたフィルター条件を選択することです。

複数のフィルターを追加して、関心のあるガベージコレクションに絞り込むことができます。 アクティブなフィルターはテーブル上部にラベルとして表示されます。ネストされたGCフェーズテーブルからフィルターを追加することも可能です。

テレメトリー

GCプローブは複数のテレメトリーを生成し、これらは「Telemetries」プローブビューで確認できます。

GCの一時停止を最小限に抑えることに関心がある場合は、最上部にある「Longest pause」テレメトリーが最も有用です。 テレメトリーの時間軸に沿ってドラッグすることで、「Garbage Collections」ビューで対応するガベージコレクションを選択できます。 垂直方向の解像度を上げるには、上部のドロップダウンから単一のテレメトリーを選択するか、テレメトリーの名前をクリックします。

上のスクリーンショットでは、一時停止の合計の時系列変化を確認できます。JProfilerは、記録されたデータのヒストグラムを構築することで合算可能な測定値を提示します。 ビンの幅は利用可能な水平スペースに依存するため、ヒストグラムのビンはズームレベルに応じて、また「scale to fit」が有効な場合はウィンドウの幅に応じて変化します。 変化しないのは、すべてのヒストグラムビンの下にある合計面積です。

ヒープおよびメタスペースのテレメトリーは、ガベージコレクションを展開したときに表示される統計情報に基づいています。 これは、完全なプロファイリングセッションにおけるメモリテレメトリーのようにデータが定期的にサンプリングされるわけではないことを意味します。 ある期間にガベージコレクションが発生しない場合、データは存在しません。 割り当てアクティビティが少ないJVMでは、時間軸に沿って2つのガベージコレクション間でグラフが単に補間されるだけの長い期間が存在することがあります。

これらのテレメトリーにはそれぞれ、「Before GC」と「After GC」の2本のデータラインがあります。 通常、「Used Heap」テレメトリーではその差が大きくなります。各時点で、2本のデータラインの値を比較することで、ガベージコレクションがどれだけの処理を実行したかを確認できます。 正確な値を確認するにはツールチップを参照してください。「Committed heap」テレメトリーおよびメタスペーステレメトリーでは、両ラインの差は多くの場合小さくなります。

JFRスナップショットを分析している場合、 jdk.GCHeapSummary JFRイベントタイプからの同じデータが、テレメトリーセクションの「Memory」テレメトリーでも使用されます。 ただしその場合、「Before GC」と「After GC」の両方の値が同じデータラインに表示され、GCプローブテレメトリーのようにデータが1秒ごとの粒度に集約されないため、グラフの表示は異なります。

GCサマリー

GCサマリーには、記録期間全体で集約された測定値が表示されます。 各測定項目では、ガベージコレクションの回数のほか、平均値、最大値、合計値が提供されます。 最上部にある最も重要なデータは、アプリケーションの生存性に直接影響を与える「Pause times」です。

もう1つのトップレベルカテゴリにはすべてのコレクションの合計時間が表示され、さらにYoungコレクションとOldコレクションの2つのサブカテゴリに分割されます。

GC構成

ガベージコレクターをチューニングする際、明示的に設定できるプロパティ、またはガベージコレクター自体によって暗黙的に設定される共通プロパティを確認したい場合があります。

これらのプロパティはすべてのガベージコレクターに共通しており、ガベージコレクター間の違いを理解するのに役立ちます。

GCフラグ

最後に、GC固有のフラグは、ガベージコレクターのどのプロパティをチューニングできるかを把握させ、その実際の値を確認できるようにします。

「Origin」列にはフラグがどのように設定されたかが表示されます。「Default」の値は標準設定から変更されていないものであり、 「Ergonomic」フラグはガベージコレクターによって自動的に調整されたものです。 コマンドラインで特定のGCフラグを設定した場合、Originには「Command line」と表示されます。