注意: Java Flight Recorderを本番で使用するには、商用ライセンスが必要です。商用機能の詳細とそれらを有効化する方法については、http://www.oracle.com/technetwork/java/javaseproducts/ にアクセスしてください。 |
Java Flight Recorder (JFR)は、実行中のJavaアプリケーションに関するデータを収集、診断およびプロファイリングするツールです。Java Virtual Machine (JVM)に統合されていて、パフォーマンスのオーバーヘッドがほとんど発生しないため、高負荷の本番環境でも使用できます。デフォルト設定を使用する場合、パフォーマンスへの影響は1%未満です。一部のアプリケーションでは、この値が格段に低くなる可能性があります。ただし、実行時間の短いアプリケーション(本番環境で実行される種類のアプリケーションではない)では、相対的な起動/準備時間が長くなる可能性があり、パフォーマンスへの影響が1%を超える可能性があります。JFRは、JVMおよびそこで実行されているJavaアプリケーションに関するデータを収集します。
その他の類似したツールと比べて、JFRには次のような利点があります。
より適切なデータの提供: JFRは、ランタイムの様々な部分からデータを取得し、取得したデータがシステムの実際の状態を表すように重要な作業を行っています。この作業の例には、観察者効果を最小化することや、セーフ・ポイント外部のサンプルを取得することが含まれます。
より適切なデータ・モデルの提供: データ・モデルは、自己記述的です。記録には、サイズにかかわらず、データを理解するために必要なすべてのものが含まれます。
より優れたパフォーマンスの提供: フライト・レコーダ・エンジンは、それ自体パフォーマンスのために最適化されています。データ取得によって最適化が元に戻されないように、または他の形式でパフォーマンスに悪影響が出ないように注意されています。一部のデータは、ランタイムによってすでに取得されているため、事実上コストなしで取得できます。
サード・パーティのイベント・プロバイダの許可: APIのセットによって、JFRでは、WebLogic Serverや他のOracle製品を含むサード・パーティ製アプリケーションからデータを取得できます。
総所有コストの削減: JFRは、問題の診断とトラブルシューティングにかかる時間を短縮し、運用コストを削減して業務の中断を低減し、問題解決までの時間を短縮して、システム効率を向上させます。
JFRの主な用途は次のとおりです。
プロファイリング
JFRは、実行中のシステムに関する情報を継続的に取得します。このプロファイリング情報には、(プログラムの時間経過が発生した場所を示す)実行プロファイリング、(スレッドが実行されない理由を示す)スレッド・ストール/待機時間プロファイリング、(割当てプレッシャの場所を示す)割当てプロファイリング、ガベージ・コレクションの詳細などが含まれます。
ブラック・ボックス分析
JFRは継続的に情報を循環バッファに保存します。オーバーヘッドは非常に少ないため、フライト・レコーダは常に有効化できます。後で、特定の例外の原因を見つけるときに、この情報にアクセスできます。
サポートおよびデバッグ
Oracleサポートに連絡する際には、JFRによって収集されたデータが、Javaアプリケーションの問題を診断しやすくするうえで不可欠となる可能性があります。
Java Flight Recorderは、イベントに関するデータを収集します。イベントは特定の時間に、JVMまたはJavaアプリケーション上で発生します。各イベントには、名前、タイム・スタンプおよびオプションのペイロードがあります。ペイロードとは、イベントに関連するデータ(CPU使用率、イベント前後のJavaヒープ・サイズ、ロック保有者のスレッドIDなど)です。
ほとんどのイベントには、イベントの発生元のスレッド、イベント発生時のスタック・トレース、およびイベントの期間に関する情報も含まれます。イベントで使用可能な情報を使用すれば、JVMおよびJavaアプリケーションに関するランタイムの詳細を再構築できます。
JFRは、次の4種類のイベントに関する情報を収集します。
インスタント・イベントは瞬時に発生し、すぐにログに記録されます。
持続イベントは、開始時間と終了時間を持ち、完了時にログに記録されます。
時間指定イベントは、指定した時間間隔の長さを超えて続くイベントのみを記録するために、オプションのユーザー定義しきい値を持つ持続イベントです。これは、その他の種類のイベントには設定できません。
サンプル・イベント(リクエスト可能なイベントとも呼ばれる)は、一定間隔でログに記録され、システム・アクティビティのサンプルを提供します。サンプリングが発生する頻度を構成できます。
JFRは、実行中のシステムをきわめて高い詳細レベルでモニターします。このため、データが大量に生成されます。オーバーヘッドをできるだけ小さく保つには、記録されるイベントを実際に必要な種類に制限します。ほとんどの場合、非常に短い期間のイベントは重要ではないため、期間が特定の意味のあるしきい値を超過しているイベントに記録を制限します。
JFRは、JVM(内部API経由)およびJavaアプリケーション(JFR API経由)からデータを収集します。このデータは、グローバルなインメモリー・バッファにフラッシュされる小さなスレッドローカル・バッファに格納されます。その後、グローバルなインメモリー・バッファ内のデータはディスクに書き込まれます。ディスク書込み操作はコストが高いので、記録対象として有効にするイベント・データを注意深く選択することで、その操作を最小限に抑えるよう努力すべきです。バイナリ形式の記録ファイルの形式は非常にコンパクトであるため、アプリケーションは効率的に読取りと書込みが可能です。
様々なバッファ間で情報が重複することはありません。個々のチャンクのデータは、メモリー内とディスク上でどちらかで使用可能ですが、両方の場所で使用することはできません。これは、次のことを示します。
ディスク・バッファにフラッシュされていないデータは、電源障害時には使用できません。
JVMがクラッシュしても、一部のデータはコア・ファイル(つまり、インメモリー・バッファ)内で使用でき、一部のデータはディスク・バッファ内で使用できます。JFRでは、このようなバッファをマージする機能は提供されていません。
JFRによって収集されたデータが使用可能になるまでに、短時間の遅延が発生する可能性があります(たとえば、表示可能になる前に、別のバッファに移動する必要がある場合)。
データが複数のスレッド・バッファからチャンク単位で収集されると、記録ファイル内のデータの順序が時系列にならない場合があります。
JVMがクラッシュしないようにするために、イベントの順序が下げられる場合もあります。ディスクに十分な速さで書き込むことができないデータは、すべて破棄されます。これが発生すると、どの期間に影響が及んだかについての情報が記録ファイルに追加されます。この情報のログは、JVMのロギング機能にも記録されます。
どのデータもディスクに書き込まれないようにJFRを構成できます。このモードでは、グローバル・バッファは循環バッファとして機能し、バッファがいっぱいになった時点でもっとも古いデータが破棄されます。この非常にオーバーヘッドの低い操作モードでも、問題の根本原因分析に必要となる重要なデータはすべて収集されます。グローバル・バッファでは最新のデータが常に使用可能となっているため、操作や監視システムによって問題が検出されるたびに、オン・デマンドでそれをディスクに書き込むことができます。ただし、このモードで使用可能なのは最後の数分間のデータだけなので、それには最新のイベントしか含まれていません。長期にわたる操作の全履歴を取得する必要がある場合には、イベントが定期的にディスクに書き込まれるデフォルト・モードを使用してください。
JFRは、次のコンポーネントで構成されています。
JFRランタイムは、記録を生成するJVM内部の記録エンジンです。ランタイム・エンジン自体は、次のコンポーネントで構成されています。
エージェントは、バッファ、ディスクI/O、MBeanなどを制御します。このコンポーネントでは、CおよびJavaコードで作成された動的ライブラリが提供され、JVMに依存しない純粋なJava実装も提供されます。
プロデューサはデータをバッファに挿入します。JVMとJavaアプリケーションから、および(Java API経由で)サード・パーティ製のアプリケーションからイベントを収集できます。
Java Mission Control (JMC)のフライト・レコーダ・プラグインにより、グラフィカル・ユーザー・インタフェース(GUI)を使用してJMCクライアントからJFRを操作し、記録の開始、停止および構成に加え、記録ファイルの表示を行うことができます。
デフォルトでは、JFRがJVMで無効になっています。JFRを有効にするには、-XX:+FlightRecorder
オプションを付けてJavaアプリケーションを起動する必要があります。JFRはJava Platform, Standard Edition (Oracle Java SE AdvancedおよびOracle Java SE Suite)に基づく市販パッケージ内でのみ使用可能な市販の機能であるため、-XX:+UnlockCommercialFeatures
オプションを使用して市販機能を有効にする必要もあります。
たとえば、MyApp
という名前のJavaアプリケーションの起動時にJFRを有効にするには、次のコマンドを使用します。
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder MyApp
また、(JDK 8u40以降を使用する場合)JMC自身内から実行時にJFRを有効化できます。新規フライト記録の開始時に、これを示すダイアログ・ボックスが表示されます。
Commercial Features are not enabled in the JVM. To start a Flight Recording, you need to enable Commercial Features. Do you want to do that now?
「はい」をクリックして、これらの機能を有効化します。
適切なjcmd
診断コマンドを使用して、実行中のJVMでJava Flight Recorderを有効化することもできます。例については、セクション2.2「診断コマンドの使用方法」を参照してください。
JavaScript実装のNashornなどのJVMでラムダ形式に依存している代替言語を実行する場合、スタック・トレースの深度をかなり深くすることができます。確実に大量のスタックを含むスタック・トレースを正しくサンプリングするには、フライト・レコーダ・スタックの深度を増やす必要がある場合があります。その値を1024に設定すれば、通常十分です。
java -XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=stackdepth=1024 MyApp
JFRメソッド・プロファイラの優れた特性は、スタックをサンプリングするために、スレッドがセーフ・ポイントに達している必要がないことです。ただし、スタックをセーフ・ポイントでしか移動しないことはよくあるケースであるため、HotSpotは通常、コードの非セーフ・ポイントの部分のメタデータを提供しません。つまり、このようなサンプルはコマンド行番号とBCIに正しく解決されません。次のように指定する場合は除きます。
-XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints
DebugNonSafepoints
では、コンパイラはセーフ・ポイントではないコ-ドの部分の必要なメタデータも生成します。