我有一个无头的应用程序,需要能够通知管理员有问题。我构建了一个电子邮件通知框架供它使用,基本上如果抛出并捕获异常,取决于代码中的区域和异常的重要性,它可以被传递到警报通知框架,触发电子邮件出去使用堆栈跟踪和其他调试信息列出的管理员。
这很有效。
在部署之前,我正在通过它的步伐。我的一个测试是从代码中的随机点抛出一个未处理的异常 - 模拟一个潜在的严重运行时问题,其中抛出了我们没想到的异常。
例如,这是我插入测试未处理异常的方法:
/**
* Closes connection.
*/
public void closeConnection() {
if (true)
throw new NullPointerException("Test unexpected exception NPE");
LOG.info("Closing SFTP connection");
getSftpChannel().exit();
getSession().disconnect();
LOG.debug("SFTP Connection closed");
}
代码运行,当它到达这个未处理的异常时,程序硬锁(因为异常被抛出,sftp连接线程永远不会被关闭,所以它保持jvm打开直到连接超时)。
我原以为它会崩溃JVM,或者将它传递给它的调用者,最终会冒泡到警报系统。
在这种情况下,我假设这个NPE会抛出这个异常,不是由它的调用者或调用者的调用者等处理的,所以它应该冒泡到main()然后崩溃JVM,因为即使是主没有抓住Exception
或NPE。
Question
:这里发生了什么,我怎样才能确保这样的场景不会停留在制作中?我刚刚在main()中使用了一个巨大的catch-all catch子句并让它捕获所有Exception
以便处理每个异常?
EDIT FOR CLARITY:
问题或多或少 - Why does an unhandled exception that is not explicitly thrown in a method's signature, nor handled by a caller, not crash the JVM?
答案 0 :(得分:1)
使用finally块确保连接已关闭。
public void closeConnection() {
try {
if (true)
throw new NullPointerException("Test unexpected exception NPE");
} finally {
LOG.info("Closing SFTP connection");
getSftpChannel().exit();
getSession().disconnect();
LOG.debug("SFTP Connection closed");
}
}
答案 1 :(得分:1)
回答你的问题:为什么未在方法的签名中显式抛出或由调用者处理的未处理异常不会使JVM崩溃?
假设此代码在Thread中运行,原因是,除非您在Thread类或Thread实例上设置UnhandledExceptionHandler
,否则'main'线程组是默认的{{ 1}}。默认情况下,线程组通过将堆栈跟踪记录到system.out来处理未处理的异常,线程“死”并且JVM不会崩溃。
您可能需要考虑实施一个UnhandledExceptionHandler,它使用您的电子邮件框架来通知您这些失败。
正如其他海报所建议的那样,代码应该清理finally块中的Channels和Session等资源。