【发布时间】:2023-03-19 19:20:01
【问题描述】:
这是假设我们不调用 .printstacktrace 方法 - 只是抛出和捕获。
我们正在考虑这样做以解决一些性能瓶颈。
【问题讨论】:
-
如果你想要性能,你真的不应该抛出异常,这应该只用于不影响性能的异常情况。也许您可以毫无例外地做您尝试的事情?
标签: java performance exception exception-handling jvm
这是假设我们不调用 .printstacktrace 方法 - 只是抛出和捕获。
我们正在考虑这样做以解决一些性能瓶颈。
【问题讨论】:
标签: java performance exception exception-handling jvm
不,堆栈跟踪是在构造异常对象时生成的,而不是在抛出异常对象时生成的。 Throwable() 构造函数调用 fillInStackTrace()。 (至少在 Sun/Oracle 的 JDK 6 for Windows 中。)
【讨论】:
fillInStackTrace() 什么都不做
如上所述,抛出异常时不会生成堆栈跟踪。相反,它们是在构造异常时生成的。我已经在下面测试过了。 在我看来,这并不直观。发生错误的地方是抛出异常的地方,而不是构造它的地方。
class ExceptionNewVsThrow {
private static RuntimeException instantiateException() {
return new RuntimeException("Hello");
}
private static void test1(Exception exception) throws Exception {
throw exception;
}
public static void main(String[] args) throws Exception {
Exception exception = instantiateException();
test1(exception);
}
}
输出是:
Exception in thread "main" java.lang.RuntimeException: Hello
at FSystem.experimental.exceptions.ExceptionNewVsThrow.instantiateException(ExceptionNewVsThrow.java:18)
at FSystem.experimental.exceptions.ExceptionNewVsThrow.main(ExceptionNewVsThrow.java:26)
注意堆栈跟踪如何提到 main 和 instantiateException,但没有提到 test1
【讨论】:
在调用 printStackTrace() 方法时不会延迟构建
Neal Gafter(构建 Java 团队的前 Sun 工程师)提到了异常性能here:
异常中最昂贵的部分 到目前为止的处理是捕获堆栈 创建异常时的跟踪
另外,请参阅this question。
【讨论】:
在构造异常时捕获堆栈跟踪。
如果你真的不关心堆栈跟踪,你可以构造一个异常并多次抛出它,但它看起来像一个 hack,可能会令人困惑。
【讨论】:
Throwable 对象捕获当前堆栈(使用本机代码),无论是否打印。这就是为什么不应(ab)将异常用于控制流的原因。
【讨论】:
仅供参考。您可以重载 fillInStackTrace 以避免性能损失。当我们需要某些不关心堆栈跟踪的异常时,我们会在 twitter 上执行此操作。
play 框架在 play 1.3.x 行中也能做到这一点。
另外,你可以断点 fillInStackTrace 来查看它是在构造时完成的。
【讨论】: