什么是 Shutdown Hook
Shutdown Hook 是一种比较特殊的结构,一般用于在 JVM 关闭之前,需要执行的一些操作的时候。常见的,比如说你的程序退出时需要做一些清理工作的时候,就可以考虑使用Shutdown Hook。但是如果你的JVM是非正常退出的,比如接收了SIGKILL,这个时候就不能保证shutdown hook能够正常执行。
使用方法
在java程序中,可以通过添加关闭钩子函数,实现在程序退出时关闭资源、平滑退出的功能。
JVM自带的shutdownHook
特点: jvm自带,使用方便,多个钩子间是并行执行的
主要就是通过 Runtime.addShutDownHook(Thread hook) 来实现的。下面我们来简单看一个示例
1 | public class ShutDownHookTest |
监听 Spring 的 ContextClosedEvent
以下是 Spring 官网的对于 ContextClosedEvent 的描述
实现ApplicationListener接口,监听ContextClosedEvent
1 |
|
实现 DisposableBean 接口
1 |
|
使用注解@PreDestory
1 |
|
应用场景
程序正常退出
程序出现异常
使用 System.exit()
终端使用 Ctrl+C 触发的中断
系统关闭
OutofMemory宕机
使用 Kill pid 杀死进程(使用kill -9是不会被调用的)
JVM Shutdown Hook 注意事项
Shutdown Hook不能保证一定执行
如果JVM crashe了, Shutdown Hook并不能保证一定执行。例如如果收到了SIGKILL的时候,程序会立刻终止执行,JVM立刻退出,导致没有机会执行Shutdown Hook.如果调用了Runtime.halt()的情况下,也可以导致JVM在没有执行Shutdown Hook的时候直接退出。当然,如果一个程序正常结束,会在JVM退出去调用Shutdown Hook。如果JVM因为用户要求中断或者是接受到SIGTERM,也是会调用Shutdown Hook的。Shutdown Hook是可以被强制中断的
即使已经开始执行Shutdown Hook,也是可以被中断的,比如当接收到了SIGTERM,但是shutdown hook没有在一定时间内完成,也是会被强制中断,导致shutdown hook没有完整执行。所以一般在Shutdown hook中的操作都应该是可以快速执行完毕,不应该是一些long time的任务。Shutdown Hook可以有多个
一个程序中可以注册多个shutdown hook,但是JVM执行shutdown hook的时候是一个任意顺序,并且JVM执行hook的时候是并发的。Shutdown hook中不可以regist/unregister shutdown hook
如果这么做了,JVM会抛IllegalStateException。Shutdown hook可以被停止
如果一个Shutdown已经开始执行了,除了例如SIGKILL这样的外部干预,需要且只能通过Runtime.halt()中断。Shutdown hook需要安全权限
