Java中没有堆栈跟踪的异常

时间:2012-07-11 14:04:30

标签: java exception stack-trace

这可能是一个非常天真的问题。

我曾经认为Throwable 中的Java总是包含堆栈跟踪。这是对的吗? 现在看起来我没有堆栈跟踪就抓住了exceptions 。是否有意义?是否可能在没有堆栈跟踪的情况下捕获异常?

5 个答案:

答案 0 :(得分:31)

可以在没有堆栈跟踪的情况下在Java中捕获Throwable对象:

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

使用。构造一个新的throwable   指定的详细消息,原因,启用或禁用抑制,以及   启用或禁用可写堆栈跟踪。

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

答案 1 :(得分:25)

对于Java 6:

由于Java 6没有Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)构造函数,我们可以使用以下技术来抑制stacktrace填充(借用Scala,来自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或者#&# 39; s亚型。

更新:有关不同用例中有关性能的一些有趣统计信息,请查看此SO question

答案 2 :(得分:8)

对于Java 7+,下面是一个例外情况,可以选择性地抑制堆栈跟踪。

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();
        }
    }
}

这可以通过以下方式证明:

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

这是基于Apache SystemML的MLContextException,其代码可在https://github.com/apache/systemml的GitHub上获得。

答案 3 :(得分:3)

在任何异常上抑制堆栈跟踪的最简单方法是

throwable.setStackTrace(new StackTraceElement[0]);

如果异常有原因,您可能需要递归地执行相同的操作。

这也可以尽可能减少堆栈跟踪的成本高昂

throwable的堆栈跟踪在

中初始化
Throwable#fillInStackTrace()

,由任何构造函数调用,因此无法避免。 实际使用stacktrace时,StackTraceElement []在

中延迟构造
Throwable#getOurStackTrace()

只有在尚未设置Throwable.stackTrace字段时才会发生。

将stacktrace设置为任何非null值,避免在Throwable#getOurStackTrace()中构造StackTraceElement [],并尽可能地降低性能损失。

答案 4 :(得分:1)

如NG。答复中所暗示的那样,如果您最初看到的是stacktrace,但随后由于相同的异常而消失,则您很可能会看到JVM优化的效果。 在这种情况下,以下问题非常相似。

Recurring Exception without a stack trace - how to reset?

NullPointerException in Java with no StackTrace

您可以关闭此JVM功能,但我建议保持启用状态,并首先努力防止错误,或者捕获并更优雅地处理它。