addShutdownHook

方法介绍

addShutdownHook 是 Runtime 类中的一个方法,方法声明:

public void addShutdownHook(Thread hook)

JDK 帮助手册中的解释如下:

注册一个新的虚拟机关闭钩子。

Java 虚拟机在响应两种事件时关闭:

  • 当最后的非守护线程退出,或者调用 exit (等同于 System.exit )方法时,程序正常退出。
  • 响应用户中断而终止虚拟机,例如键入 ^C;或者响应系统事件终止虚拟机,例如用户注销或者系统关闭。

关闭钩子只是一个已初始化但尚未启动的线程。当虚拟机开启关闭序列时,它会以不确定的顺序启动全部注册的关闭钩子,并让它们并发运行。当所有的钩子已经运行完,如果已启用退出终结方法,那么虚拟机接着会运行所有未调用的终结方法。最后,虚拟机会停止。注意,在关闭序列执行期间守护线程会继续运行,如果通过调用 exit 方法启动关闭非守护线程也会继续运行。

一旦关闭序列开始执行,只能通过调用 halt 方法停止它,该方法可强制终止虚拟机。

一旦关闭序列开始执行就不能注册一个新的关闭钩子或者取消注册已经注册的钩子。尝试这些操作会导致抛出 IllegalStateException 。

关闭钩子运行在虚拟机生命周期中的一个微妙的时间,因此应保护性地对其进行编码。特别是关闭钩子应该编写为线程安全的,并且尽可能避免死锁。关闭钩子还应该不盲目地依靠某些服务,这些服务可能已注册了自己的关闭钩子,所以其本身可能正处于关闭进程中。例如,试图使用其他基于线程的服务(如 AWT 事件指派线程)可能导致死锁。

关闭钩子应该快速地完成它们的工作。当程序调用 exit 的时候,期望的结果是虚拟机及时关闭并且退出。当由于用户注销或者系统关闭引起虚拟机终止时,底层操作系统可能只允许在固定的时间内关闭并退出。因此,在关闭钩子中尝试任何用户交互或执行长时间的计算是不可取的。就像在其他线程中一样,通过调用线程的 ThreadGroup 对象的 uncaughtException 方法,未被捕获的异常可在关闭钩子中处理。此方法的默认实现是将该异常的堆栈跟踪信息打印至 System.err 并终止线程;它不会导致虚拟机退出或停止。

仅在很少的情况下,虚拟机可能会中止,也就是没有完全关闭就停止运行。这种情况会发生在虚拟机被从外部终止时,比如在 Unix 上使用 SIGKILL 信号或在 Microsoft Windows 上调用 TerminateProcess 。如果由于例如内部数据结构损坏或试图访问不存在的内存而导致本地方法执行错误,虚拟机也可能会中止。如果虚拟机中止,则不能保证所有的关闭钩子都被运行。

参数

hook - 已初始化但尚未启动的线程对象

抛出异常

IllegalArgumentException - 如果指定的钩子已注册,或者可以确定钩子正在运行或者已运行完毕

IllegalStateException - 如果虚拟机已经处于关闭过程中

SecurityException - 如果安全管理器存在并且拒绝 RuntimePermission(”shutdownHooks“)

Since:

1.3