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