7 フライト・レコーダ

フライト・レコーダ(JFR)は、JDKに組み込まれているプロファイリングおよびイベント収集のフレームワークです。

フライト・レコーダにより、Javaの管理者および開発者は、JVMおよびJavaアプリケーションの動作状況に関する詳細な下位レベルの情報を収集できます。JMCとプラグインを使用して、JFRにより収集されたデータを視覚化できます。フライト・レコーダとJMCを組み合せると、完全なツールチェーンとなり、下位レベルの詳細な実行時情報が継続的に収集され、事後のインシデント分析が可能になります。

JFRを使用するメリット:

  • JVMイベントに関するデータが記録されます。イベントは特定の時間に記録できます。
  • JFRを使用してイベントを記録すると、実行の状態が保存され、問題を分析できます。データにはいつでもアクセスでき、問題をよく理解して解決できます。
  • JFRでは、記録プロセスのオーバーヘッドを低く抑えながら、本番システムに大量のデータを記録できます。
  • レイテンシの記録に最適です。アプリケーションが想定どおりに実行されていない状況が記録され、ボトルネックの詳細が示されます。
  • ハードウェアからオペレーティング・システム、JVM、JDKおよびJavaアプリケーション環境に至るまでの実行環境全体とプログラムがどのように相互作用するかについて洞察が提供されます。

フライト記録は、アプリケーションの起動時、またはアプリケーションの実行中に開始できます。データは、イベントと呼ばれるタイムスタンプ付きのデータ・ポイントとして記録されます。イベントは、次のカテゴリに分類されます:

  • 期間イベント: 特定の開始時間と停止時間の特定の期間に発生します。
  • インスタント・イベント: 即座に発生し、すぐにログに記録されます。たとえば、スレッドのブロックなどです。
  • サンプル・イベント: 定期的な間隔で発生し、システム全体のヘルス状態を確認します。たとえば、ヒープ診断を1分ごとに出力するなどです。
  • カスタム・イベント: JMCまたはAPIを使用して作成されたユーザー定義イベント。

また、記録テンプレートで有効化されている事前定義済イベントがあります。一部のテンプレートは、ごく基本的なイベントのみを保存し、パフォーマンスにほとんど影響を与えません。その他のテンプレートはパフォーマンスに若干のオーバーヘッドを伴い、追加データを収集するためにガベージ・コレクションをトリガーする場合もあります。フライト・レコーダに付属して次のテンプレートが<JMC_ROOT>/lib/jfrディレクトリに提供されます:

  • default.jfc: 低いオーバーヘッドで事前定義済のデータ・セットを収集します。
  • profile.jfc: default.jfcテンプレートよりも多くのデータを提供しますが、オーバーヘッドもパフォーマンスに与える影響も大きくなります。

フライト・レコーダは、次のタイプの記録を生成します:

  • 一定時間の記録: 一定時間の記録はプロファイリング記録とも呼ばれ、設定された時間だけ実行されて停止します。通常、一定時間の記録では有効になるイベントの数が多く、パフォーマンスに多少影響する場合があります。オンになるイベントは、要件に応じて変更できます。一定時間の記録は、自動的にダンプされ、開かれます。

    一定時間の記録の一般的な使用事例は次のとおりです:

    • 最もよく実行されるメソッドおよび最も多くのオブジェクトが作成される場所のプロファイルを記録する。

    • メモリー・リーク発生の指標となる、ヒープ使用量の増加を示しているクラスを探す。

    • 同期に起因するボトルネックおよび多数のこのようなユース・ケースを探す。

  • 連続記録: 連続記録は、常時オンの記録で、たとえば、最後の6時間のデータを保存します。この記録中、JFRはイベントを収集し、データをグローバル・バッファに書き込みます。グローバル・バッファがいっぱいになった場合、最も古いデータが破棄されます。ダンプをリクエストしたり、ルールによってダンプがトリガーされると、現在バッファにあるデータが指定されたファイルに書き込まれます。

    デフォルト・テンプレートでの連続記録はオーバーヘッドが少なく、有益なデータが大量に収集されます。ただし、このテンプレートは、ヒープ統計や割当てプロファイリングを収集しません。

フライト記録の開始

これらのステップに従って、JMCを使用したフライト記録を開始します。

  1. JVMブラウザでJVMを検索します。
  2. JVMを右クリックし、「フライト記録の開始」を選択します。

    「フライト記録の開始」ウィンドウが開きます。

  3. 「参照」をクリックして、記録の保存に適切な場所とファイル名を検索します。
  4. 「一定時間の記録」(プロファイリング記録)または「連続記録」を選択します。連続記録の場合は、保存するイベントの最大サイズまたは最大保持時間を指定できます。
  5. 「イベント設定」ドロップダウン・リストのフライト記録テンプレートを選択します。テンプレートで、記録するイベントを定義します。独自のテンプレートを作成するには、「テンプレート・マネージャ」をクリックします。ただし、ほとんどの場合、連続テンプレート(記録のオーバーヘッドが非常に低い)またはプロファイリング・テンプレート(より多くのデータと若干のオーバーヘッド)のいずれかが選択されます。
  6. 「完了」をクリックして記録を開始するか、「次」をクリックして選択したテンプレートで定義されているイベント・オプションを変更します。
  7. フライト記録のイベント・オプションを変更します。デフォルトの設定では、データとパフォーマンスのバランスが良くとれています。これらの設定は、要件に基づいて変更できます。

    たとえば:

    • しきい値は、記録イベントの長さです。デフォルトでは、10ミリ秒を超える同期イベントが収集されます。これは、スレッドが10msを超えてロックを待機している場合、イベントが保存されることを意味します。短い競合の詳細データを取得するには、この値を下げることができます。
    • 「スレッド・ダンプ」設定は、定期的なスレッド・ダンプを実行するためのオプションを提供します。これらは通常のテキストのスレッド・ダンプです。
  8. 「完了」をクリックして記録を開始するか、「次」をクリックして選択したテンプレートで定義されているイベント詳細を変更します。
  9. 選択したフライト記録テンプレートのイベント詳細を変更します。イベント詳細は、イベントを記録に含めるかどうかを定義します。一部のイベントでは、スタック・トレースをイベントにアタッチするかどうか、期間しきい値(持続イベントの場合)およびリクエスト期間(リクエスト可能なイベントの場合)を指定することもできます。
  10. 前のステップで設定された設定を変更する場合は「戻る」をクリックし、「終了」をクリックして記録を開始します。
    新しいフライト記録が「進行状況の表示」に表示されます。

    ノート:

    実行中の記録を表示するには、JVMブラウザでノードを展開します。記録のダンプ、記録の全体のダンプ、記録の最後の部分のダンプ、記録の編集、停止またはクローズを行うには、記録を右クリックします。プロファイリング記録を停止しても記録ファイルは作成され、プロファイリング記録を閉じると記録が破棄されます。

ノート:

JMXコンソールの「トリガー」タブを使用して、条件が満たされた場合にフライト記録が自動的に開始されるようJMCを設定できます。詳細は、「「トリガー」タブ」を参照してください。

フライト記録への現在のバッファの保存

JFRでは、記録されたデータが.jfr拡張子のファイルに保存されます。これらのJFR記録は、JMCで表示するためのバイナリ・ファイルです。グローバル・バッファの現在の内容を記録ファイルに手動でダンプできます。

  1. JVMブラウザで連続記録を右クリックして、「ダンプ」を選択します。
    「記録のダンプ」ダイアログが開きます。
  2. 「参照」ボタンをクリックし、記録のパスとファイル名を選択します。
  3. 記録全体をダンプするか、記録の最後の部分のみをダンプするか、記録の特定の間隔をダンプするかを選択します。
  4. 「終了」をクリックして、記録ダンプ・ファイルを作成します。

JMCを使用したフライト記録の分析

フライト記録ファイルをJMCで開くと、コード、メモリー、スレッド、ロック、I/Oなどの様々な領域を参照して、アプリケーションの実行時動作の様々な面を分析できます。

時間が設定された記録が終了するか、実行中の記録のダンプが作成されると、記録ファイルがJMCで自動的に開きます。ダブルクリックするか、「ファイル」メニューを使用して任意の記録ファイルを開くこともできます。フライト記録が「自動分析の結果」ページで開きます。このページは、問題を迅速に診断するのに役立ちます。たとえば、ガベージ・コレクションのチューニングまたはメモリー割当ての問題の追跡などの場合は、メモリー・ビューを使用して、個々のガベージ・コレクション・イベント、割当てサイト、ガベージ・コレクションの一時休止などに関する詳細なビューを取得できます。「I/O」ビューと「スレッド」ビューでアプリケーションのレイテンシ・プロファイルを視覚化できます。また、記録内の個々のイベントを表すビューにドリルダウンすることもできます。

「自動分析の結果」ページの表示

フライト・レコーダでは、記録からデータが抽出および分析され、「自動分析の結果」ページに色分けされたレポート・ログが表示されます。

デフォルトでは、潜在的な問題に注意が向けられるよう、黄色および赤色のスコアの結果が表示されます。レポートにすべての結果を表示するには、ページの右上にある「正常な結果の表示」」ボタン(チェック・マーク)をクリックします。同様に、結果を表として表示するには、「表」ボタンをクリックします。

ベンチマークは、主に次のものに関連する問題に分かれています:

レポートの見出し(たとえば、「Javaアプリケーション」)をクリックすると、対応するページが表示されます。

ノート:

アウトライン・ビューで、各エントリを選択して、自動分析の各ページ間を移動できます。
Javaアプリケーションの分析

「Javaアプリケーション」ダッシュボードには、Javaアプリケーションの全体的なヘルスが表示されます。

黄色および赤色のスコアを持つパラメータに注意を向けてください。ダッシュボードで、問題のある状況を的確にとらえることができます。特定のページに移動し、データを分析したり、問題を修正します。

スレッド

「スレッド」ページでは、Javaアプリケーションに属するすべてのスレッドのスナップショットが提供されます。問題の診断およびアプリケーションとJVMのパフォーマンスの最適化に役立つ、アプリケーションのスレッド・アクティビティに関する情報が表示されます。

スレッドは表に表され、各行にはグラフが関連付けられています。グラフは、問題のある実行パターンの特定に役立ちます。各スレッドの状態は、スタック・トレースとして表示され、問題領域を即時に表示できるコンテキスト情報が提供されます。たとえば、デッドロックの発生を簡単に確認できます。

ロック・インスタンス

「ロック・インスタンス」では、スレッドがロックを取得しようとしていたり、ロックに関する通知を待機しているかどうかなどのロック情報を指定しているスレッドの詳細が提供されます。スレッドがロックを取得すると、詳細がスタック・トレースに表示されます。

メモリー

アプリケーションのパフォーマンスに関する問題を検出する方法の1つは、実行時にメモリーがどのように使用されるかを確認することです。

「メモリー」ページでは、グラフにJavaアプリケーションのヒープ・メモリー使用量が表されます。各サイクルには、ヒープ・メモリーの割当ての期間を表すJavaヒープ増加フェーズがあります。その後、ガベージ・コレクションを表す急な減少があり、サイクルが最初から始まります。グラフから得られる重要な推論は、各サイクルでガベージ・コレクタがヒープを開始位置に押し下げるため、メモリー割当ての期間は短いということです。

「ガベージ・コレクション」チェック・ボックスを選択すると、グラフにガベージ・コレクション一時休止時間が表示されます。これは、ガベージ・コレクタが一時休止時間中にアプリケーションを停止し、作業を行ったことを示します。一時休止時間が長いと、アプリケーションのパフォーマンスが低下するため、対処する必要があります。

「割当て合計」チェック・ボックスを選択して、1秒当たりのメモリー割当て量を確認します。これは、「合計割当て(%)」列にパーセント値として表示することもできます。

メソッド・プロファイリング

「メソッド・プロファイリング」ページでは、特定のメソッドが実行された頻度やメソッドの実行にかかった時間を確認できます。実行に長い時間を要するメソッドを特定することでボトルネックが判明します。

プロファイリングでは大量のデータが生成されるため、デフォルトではオンになっていません。新しい記録を開始し、「イベント設定」ドロップダウン・メニューで「プロファイリング - サーバー上」を選択します。一定時間の記録を短い期間実行します。JFRは、指定されているファイルに記録をダンプします。JMCで「メソッド・プロファイリング」ページを開き、上位の割当てを確認します。上位のパッケージとクラスが表示されます。スタック・トレースで詳細を確認します。コードを調べて、メモリー割当てが特定のオブジェクトに集中しているかどうかを確認します。JFRは、問題が解決していない特定の行番号を指します。

JVM内部

「JVM内部」ページには、JVMとその動作の詳細が表示されます。

確認の必要な最も重要なパラメータの1つは、ガベージ・コレクションです。ガベージ・コレクションとは、未使用のオブジェクトを削除して、その領域を新規オブジェクトの割当てに使用できるようにするプロセスです。「ガベージ・コレクション」ページでは、実行時のシステム動作とガベージ・コレクションのパフォーマンスをよりよく理解できます。

グラフには、一時休止時間と比較したヒープ使用量、および指定した期間におけるヒープ使用量の変化が表示されます。ページには、記録中に発生したすべてのガベージ・コレクション・イベントも表示されます。ヒープに対する最長の一時休止時間を監視します。休止時間は、アプリケーションの処理中にガベージ・コレクションに時間がかかっていることを示します。ガベージ・コレクションによって解放されるヒープの領域が少なくなっていることを意味します。この状況は、メモリー・リークを引き起こす可能性があります。

メモリー管理を効果的に行うには、「コンパイル」ページを確認します。このページには、コード・コンパイルの詳細が期間とともに表示されます。大規模アプリケーションでは、コンパイルされたメソッドが多数存在する場合があり、メモリーが使い果たされてパフォーマンスの問題が発生する可能性があります。

「TLAB割当て」ページには、すべてのオブジェクト割当てに関する情報が表示されます。ここには、TLABへの割当てと、TLAB外への割当てに関する情報が表示されます。「割当て」タブには、TLABイベントに固有の3つのタイプの視覚化が用意されています。クラスによる割当て(どのクラス・インスタンスが割り当てられているか)、スレッドによる割当て(どのスレッドがオブジェクトの大部分を割り当てているか)、および割当てプロファイル(すべてのイベントの集約スタック・トレース・ツリー)です。

既存の「スレッド別」タブに加えて、新しいタブ上位メソッド別「TLAB割当て」 (スレッド・ローカル割当てバッファ)ページに追加され、上位メソッドに対してアイテム・ヒストグラムを分類できるようになりました。両方のタブにTLABに割当て(%)列とTLAB外に割当て(%)列があり、TLABの推定割当てサイズがパーセンテージとして表示されるようになりました。これらの更新により、割当てプレッシャに関連する領域の表示が容易になります。

環境

「環境」ページには、記録が行われた環境に関する情報が示されます。CPU使用率、使用されているメモリーおよびオペレーティング・システムについて理解するのに役立ちます。

「プロセス」ページを参照して、実行中の同時プロセスおよびこれらのプロセスの競合CPU使用率を確認します。多数のプロセスがCPUおよびその他のシステム・リソースを使用する場合、アプリケーションのパフォーマンスが影響を受けます。

「イベント・ブラウザ」ページで、すべてのイベント・タイプの統計を確認します。これにより、ボトルネックに着目し、アプリケーションのパフォーマンスを改善するための適切な措置を講じることができます。

「イベント・ブラウザ」ページを使用してカスタム・ページを作成できます。イベント・タイプ・ツリーで必要なイベント・タイプを選択し、ページの右上隅の「選択したイベント・タイプを使用した新しいページの作成」ボタンをクリックします。カスタム・ページが、イベント・ブラウザ・ページの下に新しいイベント・ページとしてリストされます。

JMCエージェント

JMCエージェントは、アプリケーションを再起動することなく、実行中のJVMやアプリケーションにカスタムJFRイベントをインストゥルメントまたは挿入するために使用します。JMCエージェントを使用するために、アプリケーションのソース・コードにJFRインストゥルメンテーションをプログラミングする必要はありません。

次に、JMCエージェントの機能と利点を示します:

  • XML構成を使用して、インジェクト・イベントを定義できます
  • 実行時にイベントを動的に追加できます
  • JVMエージェントは非常に汎用性が高く、エージェントをいつでも動的にロードまたはサイドロードできます
  • 発生するフットプリントは最小限です。発行するのはイベント関連の関数呼出しのみです
  • ソースを使用できない場合の本番での使用に適しています

JMCエージェント・プラグインを使用すれば、管理する構成は事前に定義されたもので、結果の変換に関する最新の情報も表示できます。

JMCエージェントを起動するには、「JVMブラウザ」タブでJMCエージェントをクリックします。エージェントを起動するための前提条件は次のとおりです:

  • エージェントJARのビルド: agent.jarをビルドするには、JMCエージェントのReadmeを参照してください。JMCエージェントの起動ダイアログで、エージェントJARファイルを参照して接続します。エージェントのビルドには、最新バージョンのコードを使用します。
  • xmlファイルでのJFRイベントの定義: xmlファイルを手動で作成しても、JMCエージェント・プリセット・マネージャ(XMLファイルを作成するためのユーザー・インタフェース)を使用してもかまいません。

ノート:

  • インストゥルメントに必要なターゲット・アプリケーションがJDK 11以上で実行されている場合は、JVM引数--add-opens java.base/jdk.internal.misc=ALL-UNNAMEDを使用してアプリケーションを実行します。
  • インストゥルメントに必要なターゲット・アプリケーションがJDK 8で実行されている場合は、JVM引数-XX:+UnlockCommercialFeatures -XX:+FlightRecorderを使用してアプリケーションを実行します。

エージェント・ライブ構成: JMCエージェントを右クリックして、エージェント・ライブ構成コンソールを開きます。このページを使用すると、エージェントに適用されたグローバル構成を、イベント・リストやイベント詳細とともに表示できます。

JMCエージェント・プリセット・マネージャ: プリセット・マネージャは、構成テンプレートの作成、編集、変更に便利です。「Windows」をクリックし、JMCエージェント・プリセット・マネージャを選択します。必要なオプションのみを指定してxmlファイルを追加することや、ファイルの編集ファイルをインポートして構成を管理することが可能です。

JMCエージェント・プラグイン

JMCエージェント・プラグインは、JDK Mission ControlにJMCエージェント機能を統合します。このプラグインを使用してJMCエージェントを起動し、JMX API経由でローカルのJVMに接続できます。

LZ4圧縮記録のサポート

JMC 9では、LZ4形式を使用して圧縮されたJFR記録の操作がサポートされるようになりました。LZ4は非常に高速なデコーダで、コア当たりの圧縮速度は500MB/秒を超え、マルチコアCPUによるスケールが可能です。

zipまたはgzipped形式でJFR記録を圧縮できます。fileユーティリティを使用して、ファイル・タイプを確認できます。LZ4ユーティリティを使用してデータ(.jfr)ファイルを圧縮するか、compress=trueを使用してレコードを圧縮します。

JRF記録を圧縮するコード例:

$ lz4 <un_compressed_filename>.jfr <compressed_filename>.jfr

Output: Compressed 8182601 bytes into 3626010 bytes ==> 44.31%

JFRスタック・トレースにアクセスするためのWebsocketサーバー

JMCでJFRイベントを選択すると、ユーザー定義のポートを介して、関連付けられたスタック・トレースにJSONデータとしてアクセスできます。視覚化は、ブラウザで直接プログラムによって制御できます。これにより、データ視覚化ツールを使用して視覚化を開発または変更できます。

Websocketサーバー・ポートはデフォルトで無効になっています。有効にするには、「Windows」「プリファレンス」「JDK Mission Control」「フライト・レコーダ」の順にクリックします。「フライト・レコーダ設定」ダイアログで、「Websocketサーバー・ポート」フィールドにポート番号を指定します。ポートを無効にするには、0を設定します。