Mic*_*ael 46 java exception stack-trace
这可能是一个非常天真的问题.
我曾经认为a Throwable
in Java
总是包含堆栈跟踪.这是对的吗?现在看起来我exceptions
没有堆栈跟踪就抓住了.是否有意义?是否有可能在没有堆栈跟踪的情况下捕获异常?
Ale*_*x W 37
在没有堆栈跟踪的情况下,可以在Java中捕获Throwable对象:
Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)
Run Code Online (Sandbox Code Playgroud)
构造具有指定详细消息的新throwable,启用,禁用启用或禁用,以及启用或禁用可写堆栈跟踪.
http://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html
man*_*nta 27
对于Java 6:
由于Java 6没有Throwable(String message, Throwable cause, boolean enableSuppression,boolean writableStackTrace)
构造函数,我们可以使用以下技术来抑制stacktrace填充(从Scala借来,从Java异常有多慢了解?)
class NoStackTraceRuntimeException extends RuntimeException {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
用法相同:throw new NoStackTraceRuntimeException ()
,或者它的子类型.
我们也可以通过扩展来做同样的事情Throwable
:
class NoStackTraceThrowable extends Throwable {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,一个小问题是你不再可以catch
使用这些异常,Exception
因为这不是子类型Exception
,而是应该捕获NoStackTraceThrowable
它或它的子类型.
更新:有关不同用例中性能的一些有趣统计数据,请查看此SO问题
Der*_*ron 10
对于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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可以通过以下方式证明:
try {
throw new SuppressableStacktraceException("Not suppressed", false);
} catch (SuppressableStacktraceException e) {
e.printStackTrace();
}
try {
throw new SuppressableStacktraceException("Suppressed", true);
} catch (SuppressableStacktraceException e) {
e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)
这是基于Apache SystemML的MLContextException,其代码可以在GitHub上的https://github.com/apache/systemml上找到.
在任何异常情况下抑制stacktrace的最简单方法是
throwable.setStackTrace(new StackTraceElement[0]);
Run Code Online (Sandbox Code Playgroud)
如果异常是有原因的,则可能需要递归执行相同的操作。
这也尽可能地减少了昂贵的堆栈跟踪创建
一个throwable的stacktrace初始化为
Throwable#fillInStackTrace()
Run Code Online (Sandbox Code Playgroud)
,任何构造函数都会调用它,因此无法避免。实际使用stacktrace时,会在以下位置延迟构造StackTraceElement []
Throwable#getOurStackTrace()
Run Code Online (Sandbox Code Playgroud)
如果尚未设置Throwable.stackTrace字段,则只会发生这种情况。
将stacktrace设置为任何非null值,可以避免在Throwable#getOurStackTrace()中构造StackTraceElement [],并尽可能降低性能损失。