Javaの例外やエラーに関するトラブルをJFR/JMCを使って調査する方法を説明します。
Javaアプリケーションで、例外を正常処理として扱う(catchして処理を継続する)ことはよくある実装です。
しかし、アプリケーションが意図せずに例外をキャッチする実装になっていると、例外が発生していることに気づかない場合があります。そのためアプリケーションのメッセージとして、例外メッセージが出力されていなくても、頻繁に例外が発生していることがあります。
例外とエラーの発生はアプリケーションの動作に影響する可能性があります。
例外とエラーの発生状況は、本製品で提供しているイベント設定ファイルを使用する場合、デフォルトで“ExceptionStatistics”イベントに記録します。
例外とエラーの調査をするには、以下の4つのイベントを使います。
イベント | イベントの記録内容 |
---|---|
ExceptionStatistics | 定期的に例外とエラーの累計発生回数 ※本製品で提供しているイベント設定ファイルを使用する場合は、1秒間隔 |
JavaExceptionThrow | 例外発生時の例外クラス名、スタックトレースなど |
JavaErrorThrow | エラー発生時のエラークラス名、スタックトレースなど |
SpecifiedJavaThrowableThrow | イベント設定ファイルで指定した例外およびエラー発生時の発生時刻、スタックトレースなど |
例外とエラーの発生状況調査
例外とエラーの発生状況は、““ExceptionStatistics”イベント”で調査します。
JMCで[アウトライン]タブの[例外]を選択します。
[統計]に例外とエラーの累計発生回数が時系列で表示されます。
[クラス]と[メッセージ]には発生したエラーのクラス名とメッセージが表示され、クラス名またはメッセージをクリックするとエラーが発生したときのスタックトレースが表示されます。
デフォルトでは、発生した例外のクラス名、メッセージ、およびスタックトレースは表示されません。例外の詳細な情報を記録するためには、“JavaExceptionThrow”イベントを有効にします。
手順は、“例外の原因特定”を参照してください。
[イベント・ブラウザ]の[イベント・タイプ・ツリー]から、[Exception Statistics]を選択すると、“ExceptionStatistics”イベントが表示され、例外とエラーの累計発生回数を時系列で参照できます。
“ExceptionStatistics”イベントに例外クラス名、例外メッセージおよびスタックトレースは表示されません。
“ExceptionStatistics”イベントは、例外とエラーの累計発生回数を定期的に記録するイベントです。イベント設定ファイルの“enabled”プロパティが“true”の場合に有効になります。
また、“period”プロパティでイベントを記録する間隔を指定します。本製品で提供するイベント設定ファイルを使用する場合、デフォルトの設定で有効になっており、1秒間隔で記録されます。
<event name="jdk.ExceptionStatistics"> <setting name="enabled">true</setting> <setting name="period">1000 ms</setting> </event>
イベント設定ファイルの設定方法は、“イベント設定ファイル”を参照してください。
例外の原因特定
例外の原因特定には、““JavaExceptionThrow”イベント”を使用します。ここでは、例外の原因特定について説明しますが、エラーの原因特定は““JavaErrorThrow”イベント”で同様に調査できます。
例外クラスには、通常、例外の原因となる詳細メッセージと、例外が発生したスタックトレースが含まれます。メッセージやスタックトレースをどのように扱うかは例外をハンドルするアプリケーションに依存し、必ずユーザに通知されるとは限りません。
JFRの“JavaExceptionThrow”イベントを有効にすることで、アプリケーションの例外ハンドルに依存せず、メッセージとスタックトレースを記録することができます。
“JavaExceptionThrow”イベントは、デフォルトでは有効になっていません。有効にするには、イベント設定ファイルを変更します。詳細は、“例外発生時にスタックトレースで調査する”を参照してください。
エラー(java.lang.Error)発生時の“JavaErrorThrow”イベントはデフォルトで有効になっています。
注意
“JavaExceptionThrow”イベントを有効にすると、すべての例外発生時に、メッセージとスタックトレースが記録されます。例外が定常的に発生するアプリケーションでは、このイベントを記録することでアプリケーション性能に影響を与える可能性があります。
性能への影響を避けたい場合は、“7.3.3.1 特定の例外やエラーの発生状況を調査する場合”を参照してください。
“JavaExceptionThrow”イベントの“enabled”プロパティの値を“false”から“true”に変更します。
<event name="jdk.JavaExceptionThrow"> <setting name="enabled" control="enable-exceptions">true</setting> <setting name="stackTrace">true</setting> </event>
ダンプしたJFRログファイルをJMCで分析します。
JMCで[アウトライン]タブの[イベント・ブラウザ]を選択します。
表示された[イベント・ブラウザ]の[イベント・タイプ・ツリー]から、[Java Exception]を選択します。
以下のように、例外が発生したときのスタックトレースが表示されますので、アプリケーションのコードに問題がないか確認します。
発生した例外の統計情報を調査するためには、[アウトライン]タブの[例外]を選択します。
例外の発生回数、発生時刻、例外クラス名、および例外メッセージが表示されます。
例外クラス名、例外メッセージを選択すると、例外が発生したときのスタックトレースが表示されますので、アプリケーションのコードに問題がないか確認します。
スタックトレースの解析は、“7.7.1 スタックトレース”を参照してください。
“JavaExceptionThrow”イベントは、例外発生時の例外クラス名、スタックトレースなどを記録するイベントです。イベント設定ファイルの“enabled”プロパティが“true”の場合に有効になります。本製品で提供するイベント設定ファイルを使用する場合、デフォルトの設定で無効になっています。
また、“stackTrace”プロパティが“true”の場合、例外発生時のスタックトレースが記録されます。
<event name="jdk.JavaExceptionThrow"> <setting name="enabled" control="enable-exceptions">false</setting> <setting name="stackTrace">true</setting> </event>
“JavaErrorThrow”イベントは、エラー発生時のエラークラス名、スタックトレースなどを記録するイベントです。イベント設定ファイルの“enabled”プロパティが“true”の場合に有効になります。本製品で提供するイベント設定ファイルを使用する場合、デフォルトの設定で有効になっています。
また、“stackTrace”プロパティが“true”の場合、エラー発生時のスタックトレースが記録されます。
<event name="jdk.JavaErrorThrow"> <setting name="enabled" control="enable-errors">true</setting> <setting name="stackTrace">true</setting> </event>
イベント設定ファイルの設定方法は、“イベント設定ファイル”を参照してください。
JFR/JMCを使って、指定した例外やエラーを調査する方法を説明します。
指定した例外の原因調査
例外調査のために、例外やエラーのクラス名を指定してイベントを記録する場合は、““SpecifiedJavaThrowableThrow”イベント”を使用します。
JMCで[アウトライン]タブの[イベント・ブラウザ]を選択します。
表示された[イベント・タイプ・ツリー]から、[Fujitsu Extended Event]の[Specified Java Throwable]を選択します。
記録した“SpecifiedJavaThrowableThrow”イベントの一覧が表示されます。
[開始時間]と[終了時間]からは例外やエラーが発生した時刻が、[Message]と[Class]からはメッセージとクラス名が確認できます。開始時刻と終了時刻は同じ時刻が表示されます。
例外が発生したときのスタックトレースが表示されますので、アプリケーションのコードに問題がないか確認します。
“SpecifiedJavaThrowableThrow”イベントは、本製品で提供するOpenJDKが実装している拡張機能であるため、“default.jfc”および“profile.jfc”のイベント設定ファイルでは使用できません。“extend.jfc”に以下のように設定されており、デフォルトで無効になっています。使用する場合は、“extend.jfc”の設定を修正した別のイベント設定ファイルを作成し、使用してください。
<event name="com.fujitsu.jdk.SpecifiedThrowableThrow"> <setting name="enabled" control="enable-exceptions">false</setting> <setting name="stackTrace">true</setting> <setting name="className">java.lang.Throwable</setting> </event>
“enabled”プロパティ
true:イベントを有効にします。
false:イベントを無効にします。
“stackTrace”プロパティ
true:発生した例外やエラーのスタックトレースをイベントに記録します。
記録されたイベントのスタックトレースには、発生した例外やエラーのクラスが継承した“java.lang.Throwable”までのクラスのコンストラクタ、および“jdk.jfr.internal.instrument.ThrowableTracer.traceThrowable”のスタックトレースが含まれています。
false:発生した例外やエラーのスタックトレースをイベントに記録しません。
“className”プロパティ
“java.lang.Throwable”を継承する例外やエラーのクラス名を完全修飾名で指定します。指定したクラス名の例外やエラーが発生した場合に、イベントを記録します。
複数のクラス名を指定する場合は“,”(カンマ)で区切ります。すべての例外やエラーを対象とする場合、“java.lang.Throwable”を指定してください。
注意
“className”プロパティで存在しないクラス名や“java.lang.Throwable”を継承しないクラス名を指定した場合、イベントに記録しません。また、エラーメッセージも出力しません。
イベント設定ファイルの設定方法は、“イベント設定ファイル”を参照してください。
注意
“className”プロパティに指定したクラスを継承した例外やエラーが発生した場合
“className”プロパティに指定した例外やエラーだけでなくそのサブクラスも、イベント記録の対象になります。
例えば、“java.langNullPointerException”の継承は以下のようになっています。
java.lang.Object java.lang.Throwable java.lang.Exception java.lang.RuntimeException java.lang.NullPointerException
“java.lang.RuntimeException”を指定したときに、“java.lang.NullPointerException”が発生すると、イベントを記録します。
注意
“java.lang.OutOfMemoryError”または、そのサブクラスのエラーが発生した場合
発生したクラス自身、またはそのスーパークラスを指定した場合でもイベントを記録しません。