【发布时间】:2010-10-10 02:33:13
【问题描述】:
假设我有一个打开数据库连接的 Java 应用程序。通常我会在 finally 块中添加一个 connection.close() ,但是在 kill 操作或任何其他异常终止的情况下不会执行此块,不是吗?作为程序员,我是否可以采取任何其他预防措施以便在应用程序退出之前正确关闭连接?
【问题讨论】:
标签: java database termination
假设我有一个打开数据库连接的 Java 应用程序。通常我会在 finally 块中添加一个 connection.close() ,但是在 kill 操作或任何其他异常终止的情况下不会执行此块,不是吗?作为程序员,我是否可以采取任何其他预防措施以便在应用程序退出之前正确关闭连接?
【问题讨论】:
标签: java database termination
您应该查看 Java (http://java.sun.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)) 的 Runtime.addShutdownHook() 方法。它允许您添加一个将在虚拟机终止时调用的钩子。您可以使用它来调用清理例程。
那将是一个 TERM 信号。 KILL 信号将杀死进程并且不允许它进行任何清理(因为接收进程无法捕获或忽略 KILL 信号)。
【讨论】:
如果外部因素破坏了您的程序,您将无能为力。显然他们想阻止它,那你怎么能阻止他们呢?
我本来打算建议 shutdown hook,但 Javadocs 声明:
在极少数情况下,虚拟机可能会中止,也就是说,在没有完全关闭的情况下停止运行。当虚拟机在外部终止时会发生这种情况,例如在 Unix 上使用
SIGKILL信号或在 Microsoft Windows 上使用TerminateProcess call。如果本地方法出错,例如破坏内部数据结构或尝试访问不存在的内存,虚拟机也可能中止。 如果虚拟机中止,则无法保证是否会运行任何关闭挂钩。
(强调我的)
【讨论】:
杀死一个程序最终会使从您的程序到您的[Oracle|SQL Server|MySQL|PostgreSQL] 服务器的TCP 流超时。
服务器将看到它并回滚任何待处理的事务。
【讨论】:
【讨论】:
当你真的被杀时(在 UNIX 上为kill -9),你无能为力。
finally-block 是您能做的最多的事情,详情请参阅SO: In Java, is the “finally” block guaranteed to be called (in the main method)?。
【讨论】:
某种程度的异常终止是不可避免的。您如何捕捉到电源线被拉到服务器上的事件?
【讨论】: