给JVM应用注册关闭钩子函数

本文详细介绍了如何控制并优雅地关闭Java应用程序,包括通过控制进程、中断信号以及Java API来终止JVM。重点讲解了JVM的关闭钩子机制,允许在JVM关闭前执行清理任务。通过Runtime.getRuntime().addShutdownHook()注册钩子函数,并展示了如何删除已注册的钩子。然而,钩子函数仅在正常关闭时执行,不适用于强制关闭或halt操作。
摘要由CSDN通过智能技术生成

启动一个服务相对容易,但有时我们需要能控制并优雅地关闭服务。本文介绍几种不同方式终止JVM应用,然后使用JAVA API管理JVM关闭回调。

关闭JVM

有两种放啊是关闭JVM:

  1. 控制进程
  2. 意外方式

下面几种情况也属于控制进程关闭JVM:

  • 最后的非精灵现场终止,例如当主线程结束时,JVM开始关闭进程。
  • 从操作系统发送中断信号,例如,按CTRL+C或注销操作系统
  • 通过Java代码调用 System.exit()

当我们希望JVM优雅地关闭,但有时JVM可能被异常方式关闭:

  • 从OS发送kill信号,例如:kill -9 <jvm_pid>
  • 从JAVA 代码调用 Runtime.getRuntime().halt()
  • OS异常死机,例如,断电或OS死机

关闭JVM的回调钩子

JVM支持在完成关闭JVM之前注册函数,这些函数是释放资源或其他任务管理的好地方。在JVM术语中,这些函数被称为关闭钩子。

关闭钩子其实是初始化但未启动的线程。当JVM开始其关闭进程时,它将以未指定的顺序启动所有注册的钩子。在运行所有钩子函数之后,JVM将停止。

注册钩子函数

注册钩子函数,可以使用 Runtime.getRuntime().addShutdownHook() 方法:

‘’’

Thread printingHook = new Thread(() -> System.out.println(“In the middle of a shutdown”));
Runtime.getRuntime().addShutdownHook(printingHook);

‘’’

这里演示在JVM关闭之前在控制台打印一些信息:


> System.exit(129);
// In the middle of a shutdown

我们看到钩子函数确实如期望在控制台打印了信息。

JVM负责启动钩子函数,如果钩子函数已经启动,JVM会抛出异常:


Thread longRunningHook = new Thread(() -> {
    try {
        Thread.sleep(300);
    } catch (InterruptedException ignored) {}
});
longRunningHook.start();

assertThatThrownBy(() -> Runtime.getRuntime().addShutdownHook(longRunningHook))
  .isInstanceOf(IllegalArgumentException.class)
  .hasMessage("Hook already running");

显然,也不能多次注册一个钩子函数:


Thread unfortunateHook = new Thread(() -> {});
Runtime.getRuntime().addShutdownHook(unfortunateHook);

assertThatThrownBy(() -> Runtime.getRuntime().addShutdownHook(unfortunateHook))
  .isInstanceOf(IllegalArgumentException.class)
  .hasMessage("Hook previously registered");

删除钩子函数

Java 提供对应的删除函数用于删除已注册的关闭钩子函数:


Thread willNotRun = new Thread(() -> System.out.println("Won't run!"));
Runtime.getRuntime().addShutdownHook(willNotRun);

assertThat(Runtime.getRuntime().removeShutdownHook(willNotRun)).isTrue();

当成功删除钩子函数后,removeShutdownHook()函数返回true。

说明

JVM仅在正常关闭时才会运行钩子函数。因此当外部暴力kill jvm进程,并不会获得机会执行钩子函数。另外,从java代码暂停JVM也不会执行钩子函数:


Thread haltedHook = new Thread(() -> System.out.println("Halted abruptly"));
Runtime.getRuntime().addShutdownHook(haltedHook);
        
Runtime.getRuntime().halt(129);

`halt()'方法强制终止当前运行的JVM,因此注册的钩子函数不会有机会执行。

总结

本文介绍关闭JVM的几种方式,然后使用运行时API注册或删除钩子函数。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值