2

アプリケーションで log4j を使用していますがException、(1) のようにロガーにオブジェクトを渡すかどうかを知りたいのですが、(2) のように を渡す場合よりも多くのリソースを消費しe.fillInStackTrace()ますか? つまり、(2)は(1)よりも安くなるでしょうか? 以下は、log4j のサンプル コードです。

private static Logger logger = Logger.getLogger(...);

try {
   ...
}
catch( Exception e ) {
   logger.error("blah blah blah", e);  // (1)

   logger.error("blah blah blah", e.fillInStackTrace());  // (2)
}

ここで少し混乱しています。明確にしてください。

4

2 に答える 2

4

さて、 を見ると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)
于 2013-08-20T07:54:21.767 に答える
2

2 つのバージョンの違いは、スタック トレースに含まれる内容です。

  • 最初のバージョンでは、元のスタック トレースになります。つまり、例外が最初にインスタンス化されたメソッド呼び出しの場合です。

  • 2 番目のバージョンでは、現在のフレームのスタック トレースになります。つまり、このメソッド呼び出し用です。


つまり、(2)は(1)よりも安くなるでしょうか?

言うのは難しいです。一方では、 への呼び出しは、コンストラクターが を呼び出しfillInStackTrace()たときに以前に行われた作業をやり直しています。一方、スタック フレームの数は少なくなります (一部のスタック フレームをポップするため)。ThrowablefillInStackTrace()

しかし、これは論外です。アプローチ (2) の動機は、パフォーマンスに関するものではありません (少なくともそうすべきではありません)。これは、ログ ファイルのスタック トレースに表示するコンテキストの量に関するものです。

于 2013-08-20T08:03:17.723 に答える