处理exception的Java程序退出
假设我有一个打开数据库连接的Java应用程序。 通常我会在finally块中添加一个connection.close(),但是在kill操作或任何其他exception终止的情况下不会执行此块,是吗? 作为程序员,在应用程序退出之前是否可以正确关闭连接,是否还有其他预防措施?
您应该查看Java的Runtime.addShutdownHook()方法( http://java.sun.com/javase/6/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread) )。 它允许您添加将在虚拟机终止时调用的挂钩。 您可以使用它来调用清理例程。
那将是一个TERM信号。 KILL信号将终止进程并且不允许它进行任何清理(因为接收进程无法捕获或忽略KILL信号)。
如果外部事件杀死了你的程序,那么你无能为力。 显然他们想阻止它,所以你怎么能阻止它们呢?
我打算建议一个关闭钩子 ,但Javadocs状态:
在极少数情况下,虚拟机可能会中止 ,即停止运行而不会干净地关闭。 当虚拟机在外部终止时会发生这种情况,例如Unix上的
SIGKILL
信号或Microsoft Windows上的TerminateProcess call
。 如果本机方法因例如破坏内部数据结构或尝试访问不存在的内存而出错,则虚拟机也可能中止。 如果虚拟机中止,则无法保证是否将运行任何关闭挂钩。
(强调我的)
杀死程序最终会使TCP
流从您的程序超时到您的[Oracle|SQL Server|MySQL|PostgreSQL]
服务器。
服务器将看到它并回滚任何挂起的事务。
- 您不应该在应用程序关闭时调用connection.close(),因为操作系统将自动关闭所有打开的文件。
- 此外,Connection的finalize()方法应该在应用程序自动关闭之前运行(如果关闭是正常的,而不是ABORTed),那应该关闭连接。
- 在任何情况下,您都可以注册shutdown-hooks ,进行所需的任何清理(同样,将在正常关机情况下运行,而不是ABORT)。
当你真的被杀死(在UNIX上kill -9
)时,你无法对此做任何事情。
finally
块是你能做的最多,参见SO:在Java中,保证被调用的“finally”块(在main方法中)? 详情。
某种程度的exception终止是不可避免的。 您如何捕获服务器上拉动电源线的事件?