【问题标题】:Handling abnormal Java program exits处理异常的 Java 程序退出
【发布时间】:2010-10-10 02:33:13
【问题描述】:

假设我有一个打开数据库连接的 Java 应用程序。通常我会在 finally 块中添加一个 connection.close() ,但是在 kill 操作或任何其他异常终止的情况下不会执行此块,不是吗?作为程序员,我是否可以采取任何其他预防措施以便在应用程序退出之前正确关闭连接?

【问题讨论】:

    标签: java database termination


    【解决方案1】:

    您应该查看 Java (http://java.sun.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)) 的 Runtime.addShutdownHook() 方法。它允许您添加一个将在虚拟机终止时调用的钩子。您可以使用它来调用清理例程。

    那将是一个 TERM 信号。 KILL 信号将杀死进程并且不允许它进行任何清理(因为接收进程无法捕获或忽略 KILL 信号)。

    【讨论】:

      【解决方案2】:

      如果外部因素破坏了您的程序,您将无能为力。显然他们想阻止它,那你怎么能阻止他们呢?

      我本来打算建议 shutdown hook,但 Javadocs 声明:

      在极少数情况下,虚拟机可能会中止,也就是说,在没有完全关闭的情况下停止运行。当虚拟机在外部终止时会发生这种情况,例如在 Unix 上使用 SIGKILL 信号或在 Microsoft Windows 上使用 TerminateProcess call。如果本地方法出错,例如破坏内部数据结构或尝试访问不存在的内存,虚拟机也可能中止。 如果虚拟机中止,则无法保证是否会运行任何关闭挂钩。

      (强调我的)

      【讨论】:

        【解决方案3】:

        杀死一个程序最终会使从您的程序到您的[Oracle|SQL Server|MySQL|PostgreSQL] 服务器的TCP 流超时。

        服务器将看到它并回滚任何待处理的事务。

        【讨论】:

          【解决方案4】:
          1. 您不需要在应用程序关闭时调用 connection.close(),因为所有打开的文件都会被操作系统自动关闭。
          2. 此外,Connection 的 finalize() 方法应该在应用程序自动关闭之前运行(如果关闭正常,而不是 ABORTed),并且应该关闭连接。
          3. 在任何情况下,您都可以注册 shutdown-hooks,以执行您需要的任何清理工作(同样,将在正常关闭情况下运行,而不是 ABORT)。

          【讨论】:

          • finalize 通常不会在应用程序正常关闭时运行。 (并且 Windows 95(!)在异常退出后不会关闭你的套接字!)
          【解决方案5】:

          当你真的被杀时(在 UNIX 上为kill -9),你无能为力。

          finally-block 是您能做的最多的事情,详情请参阅SO: In Java, is the “finally” block guaranteed to be called (in the main method)?

          【讨论】:

            【解决方案6】:

            某种程度的异常终止是不可避免的。您如何捕捉到电源线被拉到服务器上的事件?

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-08-07
              • 1970-01-01
              • 1970-01-01
              • 2010-12-05
              • 1970-01-01
              • 2011-12-12
              • 1970-01-01
              相关资源
              最近更新 更多