ネイティブ・イメージでのJDK Flight Recorder (JFR)
JDK Flight Recorder (JFR)は、GraalVMネイティブ・イメージによって現在サポートされている本番時のプロファイリング・システムです。
基本的に、-H:+AllowVMInspectionを使用して構築されたネイティブ・イメージは、Javaで記述されたJFRイベントをサポートしており、ユーザーは、Java HotSpot VMでJFRを使用する場合と同様に、引き続きjdk.jfr.Event APIとJFR自体を使用できます。ただし、実行時にJFRイベントを記録するには、JFRサポートおよびJFR記録を有効にする必要があり、このページでは、ネイティブ・イメージでのJFRの使用を開始する方法について説明します。
現在の制限事項
現時点では、JFRサポートは依然として制限されています。つまり、ほとんどのVM内部イベントや、スタック・トレースやメモリー・リーク検出などの高度な機能が不足しています。現在、JFR機能のサブセット(カスタム・イベントとシステム・イベント、ディスク・ベースの記録)を使用できます。現在、JFRはGraalVM JDK 11でビルドされたネイティブ・イメージでのみサポートされています。
JFRによるネイティブ・イメージのビルドおよび実行
JFRイベント・サポートを含むネイティブ・イメージをビルドするには、最初にイメージ・ビルド時にJFRを含める必要があります。これを行うには、-H:+AllowVMInspectionフラグを使用してイメージをビルドします:
native-image -H:+AllowVMInspection JavaApplication
JFRを含むネイティブ・イメージの場合、次のステップは、システムを使用可能にし、記録を開始し、実行時のロギングを構成することです。そのために、次のフラグを使用できます:
-XX:+FlightRecorder: JFRの有効化に使用します-XX:StartFlightRecording: アプリケーションの起動時に記録を開始するために使用します-XX:FlightRecorderLogging: JFRシステムのログ出力の構成に使用します
JFRを有効にして記録を開始するには、-XX:+FlightRecorderと-XX:StartFlightRecordingを一緒に使用します。たとえば:
./javaapplication -XX:+FlightRecorder -XX:StartFlightRecording="filename=recording.jfr"
デモの実行
この非常に単純なデモ・アプリケーションをネイティブ・イメージに変換し、そこでJFRイベントを使用する方法を確認します。次のコードをExample.javaファイルに保存します。
import jdk.jfr.Event;
import jdk.jfr.Description;
import jdk.jfr.Label;
public class Example {
@Label("Hello World")
@Description("Helps programmer getting started")
static class HelloWorldEvent extends Event {
@Label("Message")
String message;
}
public static void main(String... args) {
HelloWorldEvent event = new HelloWorldEvent();
event.message = "hello, world!";
event.commit();
}
}
アプリケーションは、1つの単純なクラスといくつかのJDKライブラリ・クラスで構成されます。これは、@Label注釈のラベルが付いたイベントをjdk.jfr.*パッケージから作成します。このアプリケーションを実行すると、何も出力されず、そのイベントが実行されるだけです。
- Javaファイルをコンパイルします:
javac Example.java - VM検査を有効にしてネイティブ・イメージにアプリケーションをビルドします:
native-image -H:+AllowVMInspection Example-H:+AllowVMInspectionオプションによって、VMの検査に使用できるJFRなどのオプション機能が有効になります。 - 実行可能ファイルを実行し、記録を開始します:
./example -XX:+FlightRecorder -XX:StartFlightRecording="filename=recording.jfr"-XX:+FlightRecorderフラグによって、組込みフライト・レコーダが有効になり、指定したファイルへの記録が開始されます。recording.jfrファイルはバイナリです。 - VisualVMを起動します。「File」→「Add JFR Snapshot」に移動し、生成されたファイルrecording.jfrを参照して開きます。
開くと、モニタリング、スレッド、例外など、チェックできるいくつものオプションが表示されますが、イベントの参照を確認することをお薦めします。次のようになります:

この後の項では、記録を構成する方法またはロギングを有効にする方法について学習します。
記録の構成
-XX:StartFlightRecordingオプションに、キーと値のペアのカンマ区切りのリストを渡して、記録をさらに構成できます。たとえば:
-XX:StartFlightRecording="filename=recording.jfr,dumponexit=true,duration=10s"
次のキーと値のペアがサポートされています:
| 名前 | デフォルト値 | 説明 |
|---|---|---|
| name | なし | 記録の識別に使用できる名前(name=MyRecordingなど) |
| settings | なし | 設定ファイル(profile.jfc、default.jfcなど)、settings=myprofile.jfcなど |
| delay | なし | 記録開始の秒(s)、分(m)、時間(h)または日(d)単位の遅延時間(delay=5hなど) |
| duration | 無限(0) | 秒(s)、分(m)、時間(h)または日(d)単位の記録期間(duration=300sなど) |
| filename | なし | 結果の記録ファイル名(filename=recording1.jfrなど) |
| maxage | 制限なし(0) | 記録されたデータをディスク上に保存する秒(s)、分(m)、時間(h)または日(d)単位の最大時間(60mなど)または制限なしの場合は0。たとえば、maxage=1d |
| maxsize | 制限なし(0) | ディスク上に保存するKB(k)、MB(M)またはGB(G)単位の最大バイト数(500Mなど)または制限なしの場合は0。たとえば、maxsize=1G |
| dumponexit | false | JVMの停止時に実行中の記録をダンプするかどうか(dumponexit=trueなど) |
JFRシステム・ロギングの構成
JFRシステムには、JFRシステムのロギングを構成するための個別のフラグ-XX:FlightRecorderLoggingもあります。使用法は-XX:FlightRecorderLogging=[tag1[+tag2...][*][=level][,...]]です。
たとえば:
-XX:FlightRecorderLogging=jfr,system=debug
-XX:FlightRecorderLogging=all=trace
-XX:FlightRecorderLogging=jfr*=error
- このオプションが設定されていない場合、ロギングは
WARNINGレベルで有効になります。 - このオプションを空の文字列に設定すると、ロギングは
INFOレベルで有効になります。 - このオプションをdisableに設定すると、ロギングが完全に無効になります。
使用可能なログ・レベルは、trace、debug、info、warning、error、offです。
使用可能なログ・タグは、all、jfr、system、event、setting、bytecode、parser、metadata、dcmdです。
それ以外の場合、このオプションでは、タグの組合せのカンマ区切りリストが必要で、それぞれにオプションのワイルドカード(*)およびレベルがあります。
- レベルなしのタグの組合せには、デフォルト・レベルの
INFOが指定されます。 - 指定されたタグの組合せと一致するタグがあるメッセージは、タグ組合せのレベルを満たす場合に記録されます。
- タグの組合せにワイルドカードがない場合、完全に同じタグを持つメッセージのみが照合されます。それ以外の場合、タグがタグの組合せのサブセットであるメッセージが照合されます。
- 複数のタグの組合せがメッセージのタグと一致する場合は、右端のタグが適用されます。
- 一致するタグの組合せがないタグを含むメッセージは、デフォルトの
WARNINGレベルでログに記録するように設定されます。 - このオプションでは、大文字と小文字が区別されません。