さて、 を見るとfillInStackTrace
、メソッドが であることがわかりますsynchronized
。同期は、モニターの取得と解放を必要とするため、Java (または任意の言語) では非常に高価な操作と見なされます。
Throwable
また、返される fromfillInStackTrace
は、呼び出された時点のコール スタックのスタック フレームに関する情報のみを記録することに注意してくださいfillInStackTrace
。この情報は JVM から直接収集され、リソースを消費するオブジェクト表現に変換されます。(最終的に、呼び出しスレッドの現在の呼び出しスタックをスキャンfillInStackTrace
するメソッドに委任します。)native
ただし、ログに何を表示するかを主に考え、その基準に従って決定する必要があります。を明示的に呼び出すfillInStackTrace
と、現在のコール スタックがログに表示されます。つまり、ブロックに到達するより深い呼び出しスタックが表示されなくなりtry
ます (例を考慮してください)。
結局のところ、(2)によって得られた情報が明示的に必要でない限り、常にバリアント(1)を使用する必要があります。解決策(2)が理にかなっている標準ログの範囲内の例を自発的に思いつくことはできませんでした。ただし、ある種のフレームワークを作成しているときにスタック トレースからノイズをカットしたい場合や、例外に関連しないいくつかのトップ スタック エントリを削除したい場合は、 (2)を利用できます。たとえば、次のようにします。ある種のものを使用しているExceptionFactory
これにより、スローされた例外が作成されます。これらのファクトリ メソッドのスタック フレームはエラーとは関係がなく、デバッグしようとしているユーザーを混乱させるため、スタック トレースにこれらのファクトリ メソッドのスタック フレームを表示したくありません。fillInStackTrace
したがって、ファクトリから例外を受け取った後に呼び出して、スタック トレースを手動で入力します。
2 つの呼び出しの違いを直感的に理解するには、次の例を見てください。
class Example {
public static void main(String[] args) {
try {
outerFunction();
}
catch (Throwable e) {
System.err.println("Outside:");
e.printStackTrace();
}
}
static void outerFunction() throws Throwable {
try {
innerFunction();
}
catch(Exception e) {
System.err.println("Inside:");
e.printStackTrace();
throw e.fillInStackTrace();
}
}
static void innerFunction() {
throw new RuntimeException("A custom exception");
}
}
これら 2 つの異なるスタック トレースを呼び出します。
Inside:
java.lang.RuntimeException: A custom exception
at Example.innerFunction(Example.java:21)
at Example.outerFunction(Example.java:13)
at Example.main(Example.java:19)
Outside:
java.lang.RuntimeException: A custom exception
at Example.outerFunction(Example.java:13)
at Example.main(Example.java:19)