【问题标题】:Why Java stack traces are generated when exceptions are constructed?为什么构造异常时会生成Java堆栈跟踪?
【发布时间】:2021-11-02 23:40:03
【问题描述】:

在 Java 中,堆栈跟踪是在构造异常时生成的,而不是在抛出异常时生成的。有谁知道这个设计背后的原因是什么?

例如,在下面的程序中,我们在方法test1中抛出了一个异常,但是我们在另一个方法中实例化了这个异常,并从ma​​in中调用了test1。结果,test1 永远不会出现在堆栈跟踪中:

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)

Are stack traces generated when a Java exception is thrown?

【问题讨论】:

  • 只是在这里猜测一下:有时异常会被捕获并重新抛出。您通常希望堆栈跟踪在重新抛出后保持原样,对吗?所以也许他们采用了这种设计,这样他们就不必区分初始投掷和重新投掷。此外,构造一个异常而不立即抛出它是不寻常的,因此通常构造时的堆栈跟踪和初始抛出时的堆栈跟踪大致相同。
  • 也许你在这里做点什么。如果 throw 语句生成堆栈跟踪,那么程序将更难以控制堆栈跟踪的生成和内容。例如,当构造异常时,您可以使堆栈跟踪无效或首先阻止它生成。如果 throw 语句影响它会更困难
  • 异常并不意味着随身携带——它们是异常并且是即时的。从抛出它们的位置构造堆栈跟踪没有任何意义:您可以从任意一组代码路径中添加(或删除)任意级别的堆栈信息,从而显着降低它们的用处。

标签: java exception constructor stack-trace throw


【解决方案1】:

在 Java 中,堆栈跟踪是在构造异常时生成的,而不是在抛出异常时生成的。有谁知道这个设计背后的原因是什么?

我认为我们无法为您提供完整的(原始)推理,因为这些决定很可能是在 Java 被称为 Oak (!) 的时代做出的(!)

但有几个优点:

  • 当您重新引发异常时,会保留原始堆栈跟踪。例如,您可以在一个线程上捕获异常,将其传递给另一个线程并重新抛出它……使用原始堆栈跟踪。
  • 您可以在自定义异常的实现中做一些事情来改变堆栈跟踪的创建方式;例如你可以完全压制它。或者,您可能会“按摩”堆栈跟踪,以向客户隐藏秘密的内部细节。
  • 捕获堆栈跟踪的成本很高。因此,如果throw 语句捕获了它,就没有机会节省捕获它的费用。 (诚​​然,现代 JVM 有另一种处理方式……但我们在这里讨论的是原始设计决策。)

【讨论】:

    【解决方案2】:

    这是 throws 语句的 Java 语言规范:https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.18

    而且 throws 语句似乎只是抛出了异常;它不会构建进入其中的堆栈跟踪。 根据设置异常的方法(Throwable 类),Java 似乎赋予了开发人员构建异常、初始化异常原因和堆栈跟踪等的责任。因此,如果这是 throws 的一部分,开发人员将不会同样的灵活性。

    因此,问题的答案是:构建堆栈跟踪作为异常构造的一部分更加强大和灵活。

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2010-12-14
      • 1970-01-01
      • 2015-01-03
      • 2011-01-05
      • 2012-09-04
      • 2017-08-06
      • 2010-09-13
      相关资源
      最近更新 更多