【问题标题】:Are stack traces generated when a Java exception is thrown?抛出 Java 异常时是否会生成堆栈跟踪?
【发布时间】:2023-03-19 19:20:01
【问题描述】:

这是假设我们不调用 .printstacktrace 方法 - 只是抛出和捕获。

我们正在考虑这样做以解决一些性能瓶颈。

【问题讨论】:

  • 如果你想要性能,你真的不应该抛出异常,这应该只用于不影响性能的异常情况。也许您可以毫无例外地做您尝试的事情?

标签: java performance exception exception-handling jvm


【解决方案1】:

不,堆栈跟踪是在构造异常对象时生成的,而不是在抛出异常对象时生成的。 Throwable() 构造函数调用 fillInStackTrace()。 (至少在 Sun/Oracle 的 JDK 6 for Windows 中。)

【讨论】:

  • 另外,如果你关心性能,你可以覆盖fillInStackTrace() 什么都不做
  • 抛出异常和构造异常是有区别的。
  • 你是绝对正确的,安迪。我没有仔细阅读这个问题。
【解决方案2】:

如上所述,抛出异常时不会生成堆栈跟踪。相反,它们是在构造异常时生成的。我已经在下面测试过了。 在我看来,这并不直观。发生错误的地方是抛出异常的地方,而不是构造它的地方。

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)

注意堆栈跟踪如何提到 ma​​ininstantiateException,但没有提到 test1

【讨论】:

    【解决方案3】:

    在调用 printStackTrace() 方法时不会延迟构建

    Neal Gafter(构建 Java 团队的前 Sun 工程师)提到了异常性能here

    异常中最昂贵的部分 到目前为止的处理是捕获堆栈 创建异常时的跟踪

    另外,请参阅this question

    【讨论】:

    • 异常会花费很多,因为每次抛出异常时,都必须创建和填充堆栈跟踪。想象一下余额转移操作在 1% 的情况下由于缺乏资金而失败。即使故障率相对较低,性能也可能受到严重影响。在此处查看源代码和基准测试结果:jquantlib.org/index.php/Cost_of_Exceptions_in_Java
    【解决方案4】:

    在构造异常时捕获堆栈跟踪。

    如果你真的不关心堆栈跟踪,你可以构造一个异常并多次抛出它,但它看起来像一个 hack,可能会令人困惑。

    【讨论】:

      【解决方案5】:

      Throwable 对象捕获当前堆栈(使用本机代码),无论是否打印。这就是为什么不应(ab)将异常用于控制流的原因。

      【讨论】:

        【解决方案6】:

        仅供参考。您可以重载 fillInStackTrace 以避免性能损失。当我们需要某些不关心堆栈跟踪的异常时,我们会在 twitter 上执行此操作。

        play 框架在 play 1.3.x 行中也能做到这一点。

        另外,你可以断点 fillInStackTrace 来查看它是在构造时完成的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-10
          • 1970-01-01
          • 1970-01-01
          • 2011-09-10
          相关资源
          最近更新 更多