JFRによるJavaアプリケーションのトラブルシューティングに必要なデータの記録とJMCによるデータ解析の方法について説明します。
JFRの記録開始方法
JFRの記録を開始する方法の一例として、Javaの拡張ランタイム・オプションを使用した方法を説明します。
Javaアプリケーション起動時に以下のオプションを指定してください。なお、パラメータの指定は任意です。
-XX:StartFlightRecording=parameterA=valueA [-XX:FlightRecorderOptions=parameterB=valueB] |
JavaアプリケーションのJFR記録を開始するオプションです。
JFRで記録を開始するときに、指定できるパラメータの名前です。指定できるパラメータは“-XX:StartFlightRecordingで指定できるパラメータ”を参照してください。
“parameterA”に指定する値です。指定できる値は“-XX:StartFlightRecordingで指定できるパラメータ”を参照してください。
複数のパラメータを使用する場合は、以下のように指定してください。
-XX:StartFlightRecording=parameter=value,parameter=value |
Javaアプリケーション起動時にJFRの挙動を制御するオプションです。“-XX:StartFlightRecording”オプションと同時に指定してください。
指定できるパラメータは“-XX:FlightRecorderOptionsで指定できるパラメータ”を参照してください。
“parameterB”に指定する値です。指定できる値は“-XX:FlightRecorderOptionsで指定できるパラメータ”を参照してください。
複数のパラメータを使用する場合は、以下のように指定してください。
-XX:FlightRecorderOptions=parameter=value,parameter=value |
パラメータ | パラメータの説明(注1) |
---|---|
delay=time | Javaアプリケーションの起動から記録を開始するまでの遅延時間を指定します。
|
dumponexit={true|false} | Javaプロセスの終了時に、JFRログファイルを生成する指定をします。
|
duration=time | 記録の継続時間を1秒以上の値で指定します。
|
filename=path(注2) | JFRログファイルを生成するファイルパスを指定します。“dumponexit=false”と一緒に指定する場合は、“duration”パラメータを指定してください。
|
name=identifier | 記録の識別子を指定します。識別子は“jcmd JFR.dump”でJFRログファイルを動的に生成する場合などに指定します。
|
maxage=time(注4) | チャンクファイルが削除されるまでの期間を指定します。 本パラメータを省略した場合、または、本パラメータ値に0を指定した場合は、アプリケーション終了時までチャンクファイルは削除されません。 チャンクファイルについては、“JFRの記録方法”を参照してください。 |
maxsize=size(注4) | ディスクバッファに記録可能なデータの最大サイズを指定します。
|
settings=path | 使用するイベント設定ファイル(.jfc)を指定します。
|
disk={true|false} | ディスクバッファに記録を書き込む指定をします
|
サイズを指定するパラメータに、単位として次の文字を指定します。
KB(キロバイト)を指定する場合: “k”または“K”
MB(メガバイト)を指定する場合: “m”または“M”
GB(ギガバイト)を指定する場合: “g”または“G”
時間を指定するオプションに、単位として次の文字を指定します。
秒を指定する場合: “s”
分を指定する場合: “m”
時を指定する場合: “h”
日を指定する場合: “d”
注意
複数のJavaプロセス起動時に同じjfrファイルを指定した場合、複数のプロセスから同じファイルに対してログを書き込むことになるため、“filename”パラメータにフルパスでファイル名を指定した場合、ログ情報として使えなくなります。
このような場合、“filename”パラメータを省略する、または“path”にディレクトリ名だけを指定してください。
JFRの記録単位に自動的に付与するIDのことを示し、JFR記録の識別に使用します。同じJavaプロセスに対して、記録が開始されるごとに、1からカウントアップします。
すべてのチャンクファイルの生存期間が“maxage”パラメータ値の期間内、およびディスクバッファの使用量が“maxsize”パラメータ値のサイズ内の場合
チャンクファイルは削除されません。
チャンクファイルの生存期間が“maxage”パラメータ値の期間を過ぎているものが存在する、およびディスクバッファの使用量が“maxsize”パラメータ値のサイズ内の場合
期間を過ぎたチャンクファイルは、ディスクバッファから削除されます。
チャンクファイルの生存期間にかかわらず、ディスクバッファの使用量が“maxsize”パラメータ値を超えた場合
“maxsize”パラメータ値内になるまで、生存期間の長いチャンクファイルが(たとえそのチャンクファイルが“maxage”パラメータ値の期間内であっても)、ディスクバッファから削除されます。
パラメータ | パラメータの説明(注1) |
---|---|
memorysize=size | グローバルバッファのサイズをバイト単位で、1メガバイト以上の値を指定します。
|
maxchunksize=size | チャンクファイルの最大サイズをバイト単位で、1メガバイト以上の値を指定します。
|
repository=path | 記録のディスク書き込み時に使用するディスクバッファのディレクトリを指定します。
|
stackdepth=depth | 記録するスタックトレースのスタックの深さを、1以上2048以下の値で指定します。
|
threadbuffersize=size | スレッドローカルバッファのサイズをバイト単位で、4キロバイト以上2ギガバイト以下の値を指定します。
|
サイズを指定するパラメータに、単位として次の文字を指定します。
KB(キロバイト)を指定する場合: “k”または“K”
MB(メガバイト)を指定する場合: “m”または“M”
GB(ギガバイト)を指定する場合: “g”または“G”
例
指定例
Javaアプリケーション起動から30秒後に記録を開始し、5分後に記録が終了します。Javaアプリケーション終了後に“C:¥tmp¥recording.jfr”でJFRログファイルを生成し、“c:\tmp\disk”に一時的に書き込まれます。
-XX:StartFlightRecording=delay=30s,duration=5m,dumponexit=true,filename=C:¥tmp¥recording.jfr -XX:FlightRecorderOptions=repository=c:\tmp\disk |
JFRの記録方法
JFRが採取するデータの記録場所にはバッファとJFRログファイルがあります。バッファは、アプリケーション実行中にJFRが使用する一時的な記憶領域で、アプリケーション終了時に削除されます。JFRログファイルは、アプリケーション実行中またはアプリケーション終了時にバッファのデータを保存するファイルで、JMCなどのツールにより解析可能なファイルです。
バッファには、メモリバッファとディスクバッファの2種類があります。メモリバッファはさらに、スレッドごとのスレッドローカルバッファとスレッド共有のグローバルバッファから構成されています。以下に各特徴について説明します。
バッファの種類 | 説明 | バッファに空きがない場合の処理 | 書き込み速度 | |
---|---|---|---|---|
メモリバッファ | スレッドローカルバッファ | Javaスレッドごとにメモリに確保されるバッファ領域。 | グローバルバッファにフラッシュします。 | 高速(メモリへの書き込み速度に依存) |
グローバルバッファ | Javaプロセスごとにメモリに確保されるバッファ領域。 |
| ||
ディスクバッファ | ディスクに一時的に確保されるバッファ領域。 | 最も古いチャンクファイルを削除する。 | 低速(ディスクへの書き込み速度、およびデータ量に依存) |
*1:JMCで読み込み可能なファイルで、ディスクバッファに生成されます。ファイル名の形式は<yyyy>_<MM>_<dd>_<HH>_<mm>_<ss>.jfrです。
フラッシュ(*1):スレッドローカルバッファのJFR記録データが、スレッドローカルバッファのサイズを超えたときに、JFR記録データをグローバルバッファにフラッシュします。
フラッシュ(*2):グローバルバッファのJFR記録データが、グローバルバッファのサイズを超えたときに、“disk”パラメータが“true”の場合、JFR記録データをディスクバッファにフラッシュします。
“disk”パラメータが“false”の場合、最も古いJFR記録データを削除します。
ダンプ(*3):Javaプロセス終了時、または“jcmd”コマンドで“JFR.dump”実行時、JFRログファイルへダンプします。
破棄(*4):ディスクバッファへのフラッシュ時に、チャンクファイルの合計サイズが、ディスクバッファのサイズを超えたときに、最も古いチャンクファイルが削除されます。
注意
循環バッファの最新のデータだけだと調査ができなくなる場合があります。
グローバルバッファは循環バッファのため、最新のデータは利用可能ですが、メモリ内で確保されるためそのサイズは大きくできません。書き込み速度は遅いですが、長期間のデータを記録するには、“disk”パラメータを“true”にし、ディスクへの書きこみを有効にしてください。
ディスバッファに記録されるイベント量が多くなると、古いデータが削除される場合があります。そのため、アプリケーション実行時に発生が予想されるイベント量やサイズを想定し、ディスクバッファサイズを見積り、“-XX:FlightRecorderOptions”の“maxsize”パラメータに適切な値を設定することを推奨します。
見積りについては、“7.3.8 ディスクバッファの見積り”を参照してください。
メモリバッファとディスクバッファ両方に書き込まれたJFR記録データを、JFRログファイル(.jfr)にダンプすることができます。トラブルシューティング時の解析では、このJFRログファイルを使用します。JFRログファイルの解析方法については“JMCの使い方”を参照してください。
JFRログファイルにJFR記録データをダンプする方法は、JFRのパラメータ設定でJavaプロセス終了時に自動的にダンプさせる方法と、Javaツールの“jcmd”コマンドを使用する方法があります。
JFRのパラメータ設定でJFRログファイルにダンプする場合は、“JFRの記録開始方法”を参照してください。
“dumponexit=true”を指定すると、Javaプロセス終了時にJFRログファイルを生成します。
JFRログファイルのパスは“filename”パラメータで指定します。指定しない場合は、javaアプリケーションのカレントディレクトリに“hotspot-pid-<JavaアプリケーションのPID>-id-<JFR記録ID>-<日付情報>.jfr”という名前で生成します。
“jcmd”コマンドを使用する場合は、以下を実行してください。
<OpenJDKインストールパス>/bin/jcmd <JavaアプリケーションのPID> JFR.dump name=<JFRの識別子> filename=<JFRログファイルの生成先> |
イベント設定ファイル
JavaプロセスおよびJavaアプリケーションで発生する様々な事象や統計情報(例えば、スレッドダンプやCPU負荷情報など)をイベントと呼び、JFRは各イベントに関するデータを記録します。イベント種別ごとに、記録の有無指定や採取情報の詳細な指定をすることができます。
イベント設定ファイルは、各設定を一括で記載するファイルです。本節で説明しているトラブルシューティングに必要なイベントの具体的な設定方法は、各項を参照してください。
イベント設定ファイルで、各イベント種別の設定は以下のXML構文で記述されています。
<event name="イベント名"> <setting name="プロパティ名">プロパティの値</setting> <setting name="プロパティ名">プロパティの値</setting> </event>
event要素のname属性にはイベント名が記述されています。
event要素の子要素であるsetting要素はイベントに指定できるプロパティです。name属性にはプロパティの名前が記述され、要素の内容はプロパティの値が記述されています。多くの場合、1つのイベントには複数のプロパティが記述されています。
例
“ThreadAllocationStatistics”イベントの記述例
“enabled”プロパティには“true”、“period”プロパティには“everychunk”が設定されています。
<event name="jdk.ThreadAllocationStatistics"> <setting name="enabled">true</setting> <setting name="period">everyChunk</setting> </event>
注意
イベントの設定について
設定を変更する場合は、プロパティの値だけを修正してください。
イベント設定ファイルは、JFR起動時に“settings”パラメータに指定します。指定方法については、“JFRの記録開始方法”を参照してください。
本製品では、以下の3つのイベント設定ファイルが使用でき、“<OpenJDKインストールパス>/jre/lib/jfr”に存在します。
また、イベント設定ファイルをカスタマイズして使用することもできます。
提供している3つの各イベント設定ファイルの特徴について説明します。
default.jfc
“settings”パラメータにイベント設定ファイルを指定しない場合は、このイベント設定ファイルを使用します。
profile.jfc
“default.jfc”より詳細なデータを記録できます。ただし、データを採取するコストは大きくなります。
extend.jfc
本製品で提供するOpenJDKが実装している拡張機能を使用します。拡張機能については“7.2.1 実行中のJavaアプリケーションからトラブルシューティングに必要なデータを記録する機能” を参照してください。
“extend.jfc”は、“default.jfc”と同じイベントの設定と、拡張機能のイベントの設定を以下のように定義しています。
~ 略 ~ <event name="com.fujitsu.jdk.SpecifiedJavaThrowableThrow"> <setting name="enabled" control="enable-exceptions">false</setting> <setting name="stackTrace">true</setting> <setting name="className">java.lang.Throwable</setting> </event> <event name="com.fujitsu.jdk.ClassLoadTrace"> <setting name="enabled" control="class-loading-enabled">true</setting> <setting name="stackTrace">false</setting> <setting name="threshold">0 ms</setting> </event> <event name="com.fujitsu.jdk.HighCPULoad"> <setting name="enabled">true</setting> <setting name="threshold">10 m</setting> <setting name="ratioThreshold">90 %</setting> </event> <event name="com.fujitsu.jdk.HighThreadCPULoad"> <setting name="enabled">true</setting> <setting name="threshold">10 m</setting> <setting name="ratioThreshold">90 %</setting> </event> ~ 略 ~
“default.jfc”、“profile.jfc”および“extend.jfc”を直接編集しないでください。
本製品提供のイベント設定ファイルの定義内容と異なる設定をする場合は、対象のイベント設定ファイルをコピーし、ファイル内の変更したいイベントの箇所をカスタマイズしてください。
例
ロードされたクラスの統計情報を記録する“ClassLoadingStatistics”イベントの設定例
デフォルトで有効になっており、1000ミリ秒に1回データを記録する設定になっています。
このイベントの場合、“enabled”プロパティの値を“false”に指定することでイベントを無効にして、データを記録しないように設定します。また、“period”プロパティの値を修正すると、定期的にデータを記録する間隔を変更できます。
<event name="jdk.ClassLoadingStatistics"> <setting name="enabled">true</setting> <setting name="period">1000 ms</setting> </event>
注意
イベント設定ファイルの文字エンコーディングについて
イベント設定ファイルの文字エンコーディングは、UTF-8から変更しないでください。
JFRは低負荷で実行中のJavaアプリケーションを監視できますが、アプリケーションやJFR起動時の設定パラメータによってオーバーヘッドが大きくなる場合があります。アプリケーションの運用に使用する場合は、スループットやレスポンスなど、性能への影響を検証した上で利用してください。
JFRのオーバーヘッドは、以下のJDKドキュメンテーションを参照してください。
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/troubleshoot/performissues001.html |
また、“イベント設定ファイル”の以下のプロパティを変更することで、より詳細なデータを採取することができますが、オーバーヘッドが増加する場合があります。
enabled
“ture”を指定するとイベントが記録されます。“false”から“true”に変更した場合、記録するイベント数が増加します。
stackTrace
“true”を指定するとイベント発生時のスタックトレースが記録されます。頻繁なスタックトレースの出力は、オーバーヘッドが増加します。
period
定期的に記録されるイベントの記録間隔を指定します。
“period”プロパティに短い間隔を指定すると、記録するイベント数が増加します。
threshold
イベント記録する処理の実行時間が、“threshold”プロパティで指定した時間以上かかった場合にイベントが記録されます。
“threshold”プロパティを小さくすると、記録するイベント数が増加します。
JMCの使い方
本マニュアルでは、JFRの記録データをダンプしたJFRログファイルを解析する方法を、JMCを例に説明します。
JMCを使用するためには、解析を行う環境にJMCをインストールします。
以下のページより、使用する環境に合わせたAdoptium JMCのバイナリファイルをダウンロードして展開してください。
https://adoptium.net/jmc/ |
JMC 8.1以降のバージョンでは、JMCを起動するためにJDK11が必要です。
以下のページより、使用する環境に合わせたAdoptium OpenJDK 11のバイナリファイルをダウンロードして展開してください。
https://adoptium.net/temurin/releases/?version=11 |
注意
Adoptium JMCおよびAdoptium OpenJDKは本製品に含まれない外部ツールです。
OSSおよび外部ツールの利用については、適用された使用条件(ライセンス条件)に従い、お客様の責任において入手、ご利用ください。また、サポートについては、対象外となります。
本節では、Windows 10の環境でJMC 8.2.0を使用する前提で説明しています。
注意
説明内で表示している画像は、実際の画面と異なる場合があります。(例えば、情報の表示順序などが異なる場合があります。)
JMCは以下の手順で起動します。起動するとJMCの画面が表示されます。
“<OpenJDK11のインストールパス>/bin”を環境変数PATHの先頭に追加します。
システム一時ディレクトリの“hsperfdata_<ユーザ名>”ディレクトリが書き込み可能な状態であることを確認します。
“<JMCのインストールパス>/JDK Mission Control/jmc.exe”を実行します。
JMCでJFRログファイルを解析するときは、JMCを起動後、[ファイル]メニューの[ファイルを開く]から解析したいjfrファイルを指定してください。
JMCにはJFRログファイルを自動で分析し、トラブルの原因になりそうな要因を表示する機能があります。
JMCの自動分析の結果は、[アウトライン]タブの[自動分析の結果]を開いて確認してください。
より詳細な情報を確認するためには、[アウトライン]タブの各機能の項目を開いてください。主な機能の説明については“JMCの[アウトライン]タブで確認できる機能”を参照してください。
イベントの詳細情報を確認する場合は、[イベント・ブラウザ]を開いて確認したいイベントを選択してください。なお、JFRのパラメータやイベント設定ファイルの設定によっては、確認できない機能があります。
具体的なトラブルの調査方法については、次項以降を参照してください。
例
以下では、GCによるアプリケーションの停止などが警告として表示されており、[メモリー]からJavaヒープ使用状況を確認し、ヒープサイズをチューニングするといった対処が考えられます。
機能 | 各機能で確認できる内容 |
---|---|
スレッド | 各スレッドのアクティブ時間など |
メモリー | Javaヒープ使用状況やクラスごとの使用率 |
ロック・インスタンス | モニターによってロックされたオブジェクト |
ファイルI/O | ファイルI/Oが発生したクラスやI/Oにかかった時間 |
ソケットI/O | ソケット通信が発生した通信先と通信回数・時間など |
メソッド・プロファイリング | JFRの定期的なサンプリングで頻出しているメソッドの統計情報 |
例外 | Javaアプリケーションで発生した例外についての情報 |
スレッド・ダンプ | 定期的に記録されるスレッドダンプ |
ガベージ・コレクション | 発生したGCの種類やかかった時間 |
GC構成 | GCに関する設定状況 |
GCサマリ | 発生したGCの統計情報 |
コンパイル | JITコンパイラでコンパイルされた対象メソッドやかかった時間 |
クラスのロード | ロードされたクラスの統計情報 |
VM操作 | SystemGCなどVMオペレーションの動作状況 |
TLAB割り当て | TLAB (Thread Local Area Buffer)の割り当て状況 |
プロセス | Javaプロセスやそれ以外のプロセスのCPU使用率、他のプロセスについての情報 |
環境変数 | Javaアプリケーションを起動した際の環境変数 |
システム・プロパティ | システムプロパティの値 |
ネイティブ・ライブラリ | Javaプロセスがロードしたネイティブライブラリ |
記録 | 記録期間などJFRの記録についての情報 |