原文出处:http://kim-miao.iteye.com/blog/1662550。感谢做者的无私分享。html
一.Runtime.addShutdownHook理解java
在看别人的代码时,发现其中有这个方法,便顺便梳理一下。api
void java.lang.Runtime.addShutdownHook(Thread hook)安全
该方法用来在jvm中增长一个关闭的钩子。当程序正常退出,系统调用 System.exit方法或虚拟机被关闭时才会执行添加的shutdownHook线程。其中shutdownHook是一个已初始化但并不有启动的线程,当jvm关闭的时候,会执行系统中已经设置的全部经过方法addShutdownHook添加的钩子,当系统执行完这些钩子后,jvm才会关闭。因此可经过这些钩子在jvm关闭的时候进行内存清理、资源回收等工做。 数据结构
二.示例代码jvm
输出以下:编码
我在这里附上JDK api上关于这个方法的说明,看这个api以为有点绕。spa
=========================================================================================================操作系统
public void addShutdownHook(Thread hook)
Java 虚拟机会为了响应如下两类事件而关闭:.net
exit
(等同于 System.exit
)方法时。或者, 关闭钩子 只是一个已初始化但还没有启动的线程。虚拟机开始启用其关闭序列时,它会以某种未指定的顺序启动全部已注册的关闭钩子,并让它们同时运行。运行完全部的钩子后,若是已启用退出终结,那么虚拟机接着会运行全部未调用的终结方法。最后,虚拟机会暂停。注意,关闭序列期间会继续运行守护线程,若是经过调用 exit
方法来发起关闭序列,那么也会继续运行非守护线程。
一旦开始了关闭序列,则只能经过调用 halt
方法来中止这个序列,此方法可强行终止虚拟机。
一旦开始了关闭序列,则不可能注册新的关闭钩子或取消注册先前已注册的钩子。尝试执行这些操做会致使抛出 IllegalStateException
。
关闭钩子可在虚拟机生命周期中的特定时间运行,所以应保护性地对其进行编码。特别是应将关闭钩子编写为线程安全的,并尽量地避免死锁。关闭钩子还应该不盲目地依靠某些服务,这些服务可能已注册了本身的关闭钩子,因此其自己可能正处于关闭进程中。例如,试图使用其余基于线程的服务(如 AWT 事件指派线程)可能致使死锁。
关闭钩子应该快速地完成其工做。当程序调用 exit
时,虚拟机应该迅速地关闭并退出。因为用户注销或系统关闭而终止虚拟机时,底层的操做系统可能只容许在固定的时间内关闭并退出。所以在关闭钩子中尝试进行任何用户交互或执行长时间的计算都是不明智的。
与其余全部线程同样,经过调用线程 ThreadGroup
对象的 uncaughtException
方法,可在关闭钩子中处理未捕获的异常。此方法的默认实现是将该异常的堆栈跟踪打印至 System.err
并终止线程;它不会致使虚拟机退出或暂停。
仅在不多的状况下,虚拟机可能会停止,也就是没有彻底关闭就中止运行。虚拟机被外部终止时会出现这种现象,好比在 Unix 上使用 SIGKILL 信号或者在 Microsoft Windows 上调用 TerminateProcess。若是因为内部数据结构损坏或试图访问不存在的内存而致使本机方法执行错误,那么可能也会停止虚拟机。若是虚拟机停止,则没法保证是否将运行关闭钩子。
hook
- 一个已初始化但还没有启动的
Thread
对象
IllegalArgumentException
- 若是指定的钩子已注册,或者能够肯定钩子正在运行或者已运行完毕
IllegalStateException
- 若是虚拟机已经处于关闭进程中
SecurityException
- 若是安全管理器存在而且拒绝
RuntimePermission
("shutdownHooks")