这可能是一个非常天真的问题。
我曾经认为Throwable
中的Java
总是包含堆栈跟踪。这是对的吗?
现在看起来我没有堆栈跟踪就抓住了exceptions
。是否有意义?是否可能在没有堆栈跟踪的情况下捕获异常?
答案 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功能,但我建议保持启用状态,并首先努力防止错误,或者捕获并更优雅地处理它。