未捕获的 RuntimeException 和 finally 子句:哪个先出现?
Posted
技术标签:
【中文标题】未捕获的 RuntimeException 和 finally 子句:哪个先出现?【英文标题】:Uncaught RuntimeException and finally clause: which comes first? 【发布时间】:2012-01-05 12:26:52 【问题描述】:RuntimeException
被抛出 try
块而不被捕获,而 finally
子句调用 System.exit()
。
public static void main(String[] args)
try
Integer.valueOf("NotANumber");
finally
System.out.println("finally");
System.exit(0);
输出是
finally
如果 System.exit(0)
从 finally 中删除,则输出为
finally
Exception in thread "main" java.lang.NumberFormatException: For input string: "NotANumber"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:449)
at java.lang.Integer.valueOf(Integer.java:554)
at exception.MyExcepTest.main(MyExcepTest.java:20)
“finally”可能出现在NumberFormatException
消息之前、之后或之间。
谁能解释一下?
【问题讨论】:
仅供参考,在我方便的系统上,上面有 Sun/Oracle 的 Java6(特别是“Java(TM) SE Runtime Environment (build 1.6.0_26-b03)”),我从来没有见过异常消息。我只看到“最后”那一行。而如果我删除System.exit(0)
行,我会看到两者(可靠地首先是“finally”)。
【参考方案1】:
finally块肯定会在main方法退出之前执行,之后JVM会打印stacktrace。
也许堆栈跟踪被打印到 System.err,并且这两个流以不可预知的方式在控制台输出中混合在一起(因为它们基本上是同时产生的)。
当您也将“finally”打印到 System.err 时会发生什么?
【讨论】:
不是“也许”。这就是你看到这个的原因。未捕获的异常将打印到错误流中。未定义顺序的原因是您的控制台将取决于首先刷新哪个缓冲区。 好的,如果我将“finally”打印到 System.err,它似乎总是在 stacktrace 之前。【参考方案2】:问题是,当抛出异常时.. JVM 第一次执行内部 finally 块的代码,然后如果捕获则抛出异常,否则它将抛出异常并终止线程。 所以这里当 System.exit(0) 出现在 finally 块中时,它会立即终止线程,这样 JVM 就没有机会抛出异常。 所以输出只是“最后 "
【讨论】:
【参考方案3】:最终块总是被执行。它是由语言保证的。如果 try 块成功终止或抛出任何异常,则会执行它。
存在已检查和未检查的异常。对于未经检查的异常(运行时和错误),您不必编写 catch 块。但是所有异常都被打印堆栈跟踪的 JVM 捕获。当您的 finally 块终止应用程序时,它没有机会打印堆栈跟踪,因此您看不到它。
通常在 finally 块中退出程序是不好的,因为即使您的代码成功运行它也会退出。更一般地说,finally 块通常用于清理,如关闭文件、套接字等,而不是更复杂的业务逻辑。
【讨论】:
我调用 System.exit() 只是为了从我的 Java 应用程序中获取返回码。否则如果应用程序被 RuntimeException 中断,返回码是什么?【参考方案4】:我们可以在 try 中使用两个块,它们是 catch 和 finally。
在抛出任何 RunTime 异常时(在 finally 之前)执行 catch 块,最后执行 finally 块,无论是否抛出异常。
所以如果你想对抛出的异常做些什么,那么你可以把它放在 catch(Excepion e) 块中。
您看到的是 JVM 有责任在终止程序执行之前执行 finally 块中写入的内容。
当程序终止时,默认情况下会显示抛出异常的踪迹。
【讨论】:
【参考方案5】:即使在 try 块中的 return 语句的情况下,finally 方法总是会被执行,但在某些情况下,在 try 块中抛出错误(运行时内存)并不能保证 finally 块完全执行。
在您的情况下,由于您没有处理异常,因此 finally 块总是被执行并且由 JVM 的 main 方法抛出异常。
【讨论】:
请阅读此how-to-answer 并按照那里的指南提供高质量的答案。以上是关于未捕获的 RuntimeException 和 finally 子句:哪个先出现?的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 7致命错误:未捕获的RuntimeException:尚未设置外观根
将 laravel 5.8 升级到 6:致命错误:未捕获的 RuntimeException:尚未设置外观根
未捕获的异常'RuntimeException',消息'无法创建目录public / assets // node_modules / font-awesome / fonts