java hook全局钩子,牛逼骚操作:Java 虚拟机关闭钩子(Shutdown Hook)!

ShutdownHook是在JVM关闭时执行的特殊代码段,用于正常或非正常退出时执行特定逻辑或资源关闭。它可以注册多个,但执行顺序不确定,且在某些极端情况下可能不会执行。安全权限是必需的,且在关闭程序开始后不能再注册。注意避免长时间计算或用户I/O操作,以防止阻塞。
摘要由CSDN通过智能技术生成

码农每日一题

长按关注,工作日每天分享一个技术知识点。

Shutdown Hooks 是一种特殊的结构,它允许开发人员插入 JVM 关闭时执行的一段代码。

用途

Application 正常退出(所有线程完成时,或在调用 System.exit(0) 时),执行特定的业务逻辑或关闭资源等操作。

Application 非正常退出(用户按下 Ctrl+C、操作系统关闭(kill pid,不带-9)),在退出时执行必要的挽救措施。

用法

示例:

1public class ShutDownHook{

2    public static void main(String[] args){

3

4        Runtime.getRuntime()

5               .addShutdownHook(new Thread(() -> System.out.println("Shutdown Hook is running !")));

6        System.out.println("Application Terminating ...");

7    }

8}

输出:

1Application Terminating ...

2Shutdown Hook is running !

可以看到 Shutdown Hook is running ! 输出在 Application Terminating ... 之后。

陷阱

在某些情况下,可能无法执行 Shutdown Hook。

如果 JVM 由于某些内部错误而崩溃,则它可能崩溃而没有机会执行一条指令。

另外,如果操作系统发出 SIGKILL 信号(在 Unix/Linux 中为 kill -9)或 TerminateProcess(Windows),则要求应用程序立即终止而无需甚至在等待任何清理活动。

除上述内容外,还可以通过调用 Runtime.halt() 方法来终止 JVM,而不允许运行 Shutdown Hook。

启动后,可以在完成之前强行关闭 Shutdown Hook。

在诸如操作系统关闭之类的情况下,有可能在 Shutdown Hook 完成之前将其终止。

在这种情况下,一旦给出 SIGTERM,O/S 将等待进程终止指定的时间。

如果该过程未在此期限内终止,则操作系统将通过发出SIGTERM(或Windows中的对应程序)来强制终止该过程。

因此,当关闭 Shutdown Hook 执行到一半时,可能会发生这种情况。

因此,建议确保 Shutdown Hook 的谨慎书写,以确保它们快速完成,并且不会引起死锁等情况。另外,JavaDoc 特别提到不应在 Shutdown Hook 中执行长时间计算或等待用户 I/O 操作。

可以有多个 Shutdown Hook,但是不能保证它们的执行顺序。

可以注册多个 Shutdown Hook,但是 JVM 无法保证其执行顺序(shutdownHooks 存放在 IdentityHashMap 中),JVM 可以按任意顺序执行关闭 Shutdown Hook,也可能会同时执行 Shutdown Hooks。

1public void addShutdownHook(Thread hook){

2    SecurityManager sm = System.getSecurityManager();

3    if (sm != null) {

4        sm.checkPermission(new RuntimePermission("shutdownHooks"));

5    }

6    ApplicationShutdownHooks.add(hook);

7}

8

9class ApplicationShutdownHooks{

10    /* The set of registered hooks */

11    private static IdentityHashMap hooks;

12    static synchronized void add(Thread hook){

13        if(hooks == null)

14            throw new IllegalStateException("Shutdown in progress");

15

16        if (hook.isAlive())

17            throw new IllegalArgumentException("Hook already running");

18

19        if (hooks.containsKey(hook))

20            throw new IllegalArgumentException("Hook previously registered");

21

22        hooks.put(hook, hook);

23    }

24}

关闭程序开始后,无法注册/取消注册 Shutdown Hook。

一旦关闭程序是由 JVM 发起的,将不在允许添加或删除任何现有的 Shutdown Hook,否则抛出 IllegalStateException 异常。

关闭程序开始后,只能由 Runtime.halt() 停止。

一旦关闭程序开始,只有 Runtime.halt()(强制终止 JVM)可以停止执行关闭序列(除了诸如 SIGKILL 之类的外部影响之外)。这意味着在 Shutdown Hook 中调用 System.exit() 将不起作用。实际上,如果在 Shutdown Hook 中调用 System.exit(),VM 可能会卡住,我们可能不得不强制终止该过程。

使用 Shutdown Hook 需要安全权限。

如果我们使用的是 Java Security Manager,则执行添加/删除 Shutdown Hook 的代码在运行时需要具有 shutdownHooks 权限。如果我们在安全的环境中未经许可调用此方法,则将导致 SecurityException。

作者:河西

链接:https://juejin.im/post/5e0d9c4b6fb9a048411a4af6

参考:https://www.geeksforgeeks.org/jvm-shutdown-hook-java/

f5381c98736df729c78d968861def246.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值