Java jvm异常捕获

Java jvm异常捕获,java,debugging,exception-handling,jvm,Java,Debugging,Exception Handling,Jvm,所以我最近编写了一个java类来扩展exception,并使用该类的一个实例来检查案例,并在发生错误时自动抛出。我发现当main的调用者捕捉到这个异常时,它说抛出异常的那一行是创建异常的那一行,而不是抛出异常的那一行。我只是想知道为什么会这样,以及这是否是jvm的预期行为,因为这不是引发异常的常见方式。如果它是预期的行为,那么它的合理解释是什么,因为抛出异常的行号似乎更有用(并且可能更容易在堆栈中跟踪)。示例案例展示了预期行为和意外行为 正常异常引发: 1 public class Test

所以我最近编写了一个java类来扩展exception,并使用该类的一个实例来检查案例,并在发生错误时自动抛出。我发现当main的调用者捕捉到这个异常时,它说抛出异常的那一行是创建异常的那一行,而不是抛出异常的那一行。我只是想知道为什么会这样,以及这是否是jvm的预期行为,因为这不是引发异常的常见方式。如果它是预期的行为,那么它的合理解释是什么,因为抛出异常的行号似乎更有用(并且可能更容易在堆栈中跟踪)。示例案例展示了预期行为和意外行为


正常异常引发:

1  public class Test
2  {
3   public static void main(String ... args) throws Throwable
4   {
5       switch(5)
6       {
7           case 1: throw new Exception("Exception");
8           case 2: throw new Exception("Exception");
9           case 3: throw new Exception("Exception");
10          case 4: throw new Exception("Exception");
11          case 5: throw new Exception("Exception");
12      }
13  }
14 }
输出:

Exception in thread "main" java.lang.Exception: Exception
    at Test.main(Test.java:11)
Exception in thread "main" java.lang.Exception: Exception
    at Test.main(Test.java:5)

我的方法(简化):

输出:

Exception in thread "main" java.lang.Exception: Exception
    at Test.main(Test.java:11)
Exception in thread "main" java.lang.Exception: Exception
    at Test.main(Test.java:5)
它说异常是从哪一行抛出的 异常是创建的,而不是从引发异常的位置创建的。我只是 想知道为什么会这样,以及这是否是jvm的预期行为 还是不

对。它不仅是有意的,而且是记录在案的。请参阅Javadoc以了解
java.lang.Throwable
:“Throwable包含创建时线程执行堆栈的快照。”如果不需要,可以在抛出它之前调用
fillInStackTrace()

通常情况下,这是创建和删除此可丢弃项的点 扔

这有点模棱两可,但99%的时间是在抛出异常时创建的。我想,当你考虑重新抛出异常时,从创建点创建堆栈跟踪更有意义,例如:

void bar() throws Exception
{
    throw Exception();
}

void foo() throws Exception
{
    try
    {
        bar();
    }
    catch (Exception e)
    {
        throw e;
    }
}

public static void main(String[] args)
{
   foo();
}
知道异常是在
bar()
中创建的比知道它是在
foo()中重新抛出的更有用。如果此信息很重要,您可以抛出一个新异常,并将原始异常作为原因参数

更新

举例来说,如果您确实想知道异常也是在
foo()
中抛出的,那么您可以在
foo()中执行此操作


但在您的示例中,您在创建异常的同时抛出异常。在这种情况下,如果异常是在其他地方创建的,您仍然希望知道它是从bar抛出的,而不是从创建它的位置抛出的。我猜正如EJP所说的,您可以通过调用fill-in-stack-trace来选择这种行为,以便更多地解释为什么他们会这样设计throws子句。我已经更新了答案。我不确定
fillInStrackTrace()
是否会有您所说的行为。对于异常处理,您确实希望它尽可能明显。特别是对于其他查看您的代码的人。也就是说,我更喜欢在相同的时间点创建和抛出异常,这是99%查看堆栈跟踪的人所期望的。我刚刚测试了它,fillInStackTrace()确实按照我的预期工作。值得注意的是,在您的示例中,堆栈跟踪显示异常从bar开始,并在到达main的过程中通过foo,即使没有foo中的额外代码。问题不在于标准惯例是什么,我知道我的方法似乎有点奇怪,但相信我,在上下文中,它是有意义的。