Java 引发未处理的异常后线程被卡住

Java 引发未处理的异常后线程被卡住,java,exception,Java,Exception,我有一个无头运行的应用程序,需要能够将问题通知管理员。我构建了一个电子邮件通知框架供其使用,基本上,如果抛出并捕获了异常,根据代码中的区域和异常的严重程度,它可能会被传递到警报通知框架,该框架会触发一封电子邮件,将堆栈跟踪和其他调试信息发送给列出的管理员 这很管用 在部署之前,我对它进行了测试。我的一个测试是从代码中的一个随机点抛出一个未处理的异常——模拟一个潜在的严重运行时问题,其中抛出的异常是我们没有预料到的 例如,以下是我插入测试未处理异常的方法: /** * Closes connec

我有一个无头运行的应用程序,需要能够将问题通知管理员。我构建了一个电子邮件通知框架供其使用,基本上,如果抛出并捕获了异常,根据代码中的区域和异常的严重程度,它可能会被传递到警报通知框架,该框架会触发一封电子邮件,将堆栈跟踪和其他调试信息发送给列出的管理员

这很管用

在部署之前,我对它进行了测试。我的一个测试是从代码中的一个随机点抛出一个未处理的异常——模拟一个潜在的严重运行时问题,其中抛出的异常是我们没有预料到的

例如,以下是我插入测试未处理异常的方法:

/**
 * 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崩溃,因为即使是main也不会捕获异常或NPE

问题
:这里发生了什么?我如何确保这样的场景不会在生产中出现?我是不是在main()中有一个巨大的catch-all-catch子句,并让它catch-all
Exception
,以便处理每个异常


为清晰起见进行编辑:
问题或多或少是--
为什么未在方法签名中显式抛出、也未由调用方处理的未处理异常不会使JVM崩溃?

使用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");
    }
}

回答您的问题:为什么没有在方法签名中显式抛出、也没有由调用方处理的未处理异常不会使JVM崩溃

假设此代码在线程中运行,原因是,除非在线程类或线程实例上设置了
UnhandledExceptionHandler
,否则“main”线程组是默认的
UnhandledExceptionHandler
。默认情况下,线程组通过将堆栈跟踪记录到system.out来处理未处理的异常,线程“死亡”,JVM不会崩溃

您可能想考虑实现一个使用您的电子邮件框架通知这些故障的非HealthExcel处理程序。


正如其他海报所建议的那样,代码应该在finally块中清理频道和会话等资源。

也许我应该更清楚一点——示例中的NPE仅用于测试目的。。。代码显然不仅仅是无缘无故地抛出新的NPE-P——因此,将整个代码库放在try/finally块中是没有意义的。将对closeConnection的调用放在finally块中是没有意义的。问题是,如果在代码库中的任何地方抛出任何未处理的异常,我就会得到这个挂起的JVM。不仅仅是在这个示例方法中,也不仅仅是在示例NPE中。问题更多的是更少的--
为什么没有在方法签名中显式抛出,也没有由调用方处理的未处理异常不会使JVM崩溃?
为什么您认为它应该崩溃?