JFR で実行時イベントを残す
🐱 この章の目次
JFR が記録するもの
Java Flight Recorder(JFR) は、Javaアプリケーション、JDKライブラリ、HotSpot JVM、OSから発生するイベントを一つの記録へ収める仕組みです。 JDK 11でOpenJDKへ導入され、JDK 21ではJDKの標準機能として利用できます。
JFRは、メソッドのサンプルだけを集めるCPUプロファイラーではありません。 GC、オブジェクト割り当て、ロック、スレッド、ファイルI/O、ソケットI/O、例外、JITコンパイルなど、時刻を持つ異なる種類のイベントを同じ記録上で比較できます。
起動中のJVMで記録する
次の例は、起動済みJVMで profile 設定の記録を2分間実行し、ファイルへ保存します。
jcmd <pid> JFR.start \
name=incident \
settings=profile \
duration=2m \
filename=incident.jfr
実行中の記録は確認、書き出し、停止ができます。
jcmd <pid> JFR.check name=incident
jcmd <pid> JFR.dump name=incident filename=snapshot.jfr
jcmd <pid> JFR.stop name=incident filename=final.jfr
JFR.dump は記録を止めずに、その時点までのデータをファイルへ書き出します。
インシデントの直前を残すには、アプリケーション起動時からサイズまたは時間で上限を設けた循環記録を動かします。
java \
-XX:StartFlightRecording=name=continuous,settings=default,maxage=2h,maxsize=256m,disk=true \
-jar app.jar
# 問題を検知した後に直近30分を保存する
jcmd <pid> JFR.dump name=continuous maxage=30m filename=incident.jfr
maxage と maxsize は古いデータを保持し続けないための上限です。
保存先の空き容量と、記録ファイルに業務データが含まれる可能性も運用設計へ含めます。
default と profile の違い
JDK 21には default.jfc と profile.jfc が含まれます。
| 設定 | 用途 | 記録量と負荷の傾向 |
|---|---|---|
default | 継続記録 | 記録対象を抑え、継続利用との均衡を取る |
profile | 時間を区切った詳細調査 | より多くのイベントを記録する |
OracleのJDK 21ガイドは default を継続記録に推奨し、典型的なオーバーヘッドを1%未満と説明しています。
この数値はすべてのアプリケーションと設定を保証する上限ではありません。
カスタムイベント、スタック深度、記録頻度、ストレージ性能でも負荷は変わるため、実際のサービスで測定します。
コマンドとJMCで読む
JDK 21の jfr コマンドは、記録の概要と定型ビューを端末へ表示できます。
jfr summary incident.jfr
jfr view hot-methods incident.jfr
jfr view gc-pauses incident.jfr
jfr print --categories GC --events CPULoad incident.jfr
JDK Mission Control(JMC) は、JFR記録を可視化して分析するOpenJDKプロジェクトです。 時間範囲を絞り、GC停止、割り当て、スレッド、I/O、ホットメソッドを同じタイムラインで追う用途に向きます。 JMCはJDKそのものには同梱されないため、利用するディストリビューションとバージョンを別に管理します。
調査では、まずメトリクスやトレースで異常が起きた時刻を絞り、JMCで同じ時間帯のイベントを比較します。 記録全体で最も多いイベントだけを見ると、正常時に長く動いた処理が異常時の短い変化を覆い隠すことがあります。