2012-07-11 36 views
33

これはおそらく非常に素朴な質問です。Javaでスタックトレースのない例外

私は、の には常ににスタックトレースが含まれていると考えました。それが正しいか? 今度はexceptionsを捕まえたようですが、スタックトレースはありません。それは理にかなっていますか?それは可能スタックトレースなしで例外をキャッチですか?

+4

JVMとは?環境?これは役に立ちますか? http://stackoverflow.com/questions/4659151/recurring-exception-without-a-stack-trace-how-to-reset –

+0

@SB。はい、これは助けになります。どうもありがとう。私は非常に似た問題があります:私は多くの例外(NPE)を持っています。 'log4j'の' error'メソッドはスタックトレースなしでいくつかの例外を記録します。 – Michael

答えて

27

それはスタックトレースせずにJavaでThrowableオブジェクトをキャッチすることが可能です:

Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace) 

は 指定された詳細メッセージ、原因、抑制有効化または無効化、および 書き込み可能なスタックトレースで新しいスロー可能オブジェクトを構築します有効または無効です。 Java 6のために

http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html

20

のJava 6がThrowable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)コンストラクタを持っていないとして、我々は技術(スカラ座から借り、How slow are Java exceptions?から知るようになった)の下に使用してスタックトレースの充填を抑制することができます

class NoStackTraceRuntimeException extends RuntimeException { 
    @Override 
    public synchronized Throwable fillInStackTrace() { 
     return this; 
    } 
} 

使用方法は同じです:throw new NoStackTraceRuntimeException()、またはそのサブタイプです。

我々はまた、Throwableを拡張することで同じことを行うことができます。

class NoStackTraceThrowable extends Throwable { 
    @Override 
    public synchronized Throwable fillInStackTrace() { 
     return this; 
    } 
} 

をしかし、小さなキャッチあなたはもはやcatchこれはExceptionのサブタイプではないので、Exceptionを使用して、これらの例外ではなく、キャッチするべきではないということですNoStackTraceThrowableかそれはサブタイプです。

更新:異なるユースケースでのパフォーマンス上のいくつかの興味深い統計は、Java 7+については、このSO question

+0

OPは本当に彼の質問でjava-6を言いましたか? –

+4

@shekharsumanいいえ、しかしJava 7はありません。この答えは、Java 6の誰かを助けるかもしれません:) – manikanta

+2

Java 1.6の外でも、これは実行可能な方法です。これによりスタックトレース全体が抑制されます(4つのパラメータコンストラクタで渡された '原因'が出力されるため)。 – DBK

6

を確認するには、ここでのスタックトレースを任意に抑制することができる例外の一例です。

public class SuppressableStacktraceException extends Exception { 

    private boolean suppressStacktrace = false; 

    public SuppressableStacktraceException(String message, boolean suppressStacktrace) { 
     super(message, null, suppressStacktrace, !suppressStacktrace); 
     this.suppressStacktrace = suppressStacktrace; 
    } 

    @Override 
    public String toString() { 
     if (suppressStacktrace) { 
      return getLocalizedMessage(); 
     } else { 
      return super.toString(); 
     } 
    } 
} 

これを用いて実証することができる:これはApache SystemMLからMLContextException、https://github.com/apache/systemmlでGitHubの上で利用可能となっているコードに基づいている

try { 
    throw new SuppressableStacktraceException("Not suppressed", false); 
} catch (SuppressableStacktraceException e) { 
    e.printStackTrace(); 
} 
try { 
    throw new SuppressableStacktraceException("Suppressed", true); 
} catch (SuppressableStacktraceException e) { 
    e.printStackTrace(); 
} 

0

任意の例外にスタックトレースを抑制するための最も簡単な方法は、例外が原因を持っている場合は、再帰的に同じことを行う必要があるかもしれません

throwable.setStackTrace(new StackTraceElement[0]); 

です。

はこれもできないので、任意のコンストラクタによって呼び出されたThrowableのためのスタックトレースが

Throwable#fillInStackTrace() 

に初期化され

できるだけ多くのスタックトレースの高価な作成を、低減し、避けてください。 スタックトレースが実際に使用される場合、のStackTraceElement []は、レイジーフィールドThrowable.stackTraceが既に設定されていない場合にのみ、起こる

Throwable#getOurStackTrace() 

に構成されています。

null以外の値にstacktraceを設定すると、Throwable#getOurStackTrace()でStackTraceElement []が構築されるのを避け、パフォーマンスペナルティをできるだけ減らします。

+1

これは機能しますが、スタックトレースを抑制することで解決したい問題を解決することはできません。スタックトレースの生成が遅いため、メッセージングに多くの例外を使用するコードが遅くなる可能性があります。これに対処するには、スタックトレースの作成を防止し、すでに作成されている場合は削除しないようにする必要があります。 - 何らかの理由でコントロールのない多数の例外が格納されている場合でも、メモリを節約するためにはあなたのアプローチは依然として有効かもしれません。 –

+0

Halo @Hans Adler、私はあなたの懸念を理解していますが、私の答えはスタックトレースのコストのかかる作成を可能な限り減らすと思います。私の最後の編集を見てください。 –

関連する問題