jvm关闭

关闭方式

正常关闭

  • 最后一个普通线程(非守护线程)结束
  • 调用了System.exit
  • 发送SIGINT信号(相当于不带参数的kill命令)或者键入Ctrl-C

强制关闭

  • 调用Runtime.halt
  • 发送SIGKILL信号(kill -9 命令)

关闭钩子(Shutdown Hook)

钩子配置方法

通过下面的设置方法可看到,关闭钩子实际为线程

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

触发调用Hook线程流程

正常关闭中,JVM首先调用所有已注册的关闭钩子。JVM并不能保证关闭钩子的调用顺序。在关闭应用程序线程时,如果有线程仍然在运行,那么这些线程接下来将与关闭进程并发进行。
当所有的关闭钩子都执行结束时,如果runFinalizersOnExit为true,那么JVM将运行终结器,然后再停止。JVM并不会停止或中断任何在关闭时仍然运行的应用程序线程。当JVM最终结束时,这些线程将被强行结束。
如果关闭钩子或终结器没有执行完成,那么正常关闭进程挂起并且JVM必须被强行关闭。
–《Java并发编程实战》

上述是书里面的介绍,下面跟着源码对照整个流程:

添加钩子

Runtime:

public void addShutdownHook(Thread hook) {
   
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
   
        sm.checkPermission(new RuntimePermission("shutdownHooks"));
    }
    ApplicationShutdownHooks.add(hook);
}

ApplicationShutdownHooks:
会检查hook线程是否被启动,是否已经添加过

其中看到第一个判断条件是判断hooks是否为空,这是因为当ApplicationShutdownHooks开始启动钩子线程后,会把hooks置为空,也意味着开始启动钩子线程后,就再也无法添加钩子线程

/* Add a new shutdown hook.  Checks the shutdown state and the hook itself,
 * but does not do any security checks.
 */
static synchronized void add(Thread hook) {
   
    if(hooks == null)
        throw new IllegalStateException("Shutdown in progress");

    if (hook.isAlive())
        throw new IllegalArgumentException("Hook already running");

    if (hooks.containsKey(hook))
        throw new IllegalArgumentException("Hook previously registered");

    hooks.put(hook, hook);
}

关闭钩子管理器的初始化

从上面代码可以看到,实际管理关闭钩子的是ApplicationShutdownHooks类,

可以看到ApplicationShutdownHooks其实是属于 用户/应用程序等级(user level) 的关闭钩子管理器(注释),该类初始化的时候,会把自己注册到虚拟机的关闭钩子队列中(Shutdown)(静态初始代码)

初始化:

/*
 * Class to track and run user level shutdown hooks registered through
 * <tt>{@link Runtime#addShutdownHook Runtime.addShutdownHook}</tt>.
 *
 * @see java.lang.Runtime#addShutdownHook
 * @see java.lang.Runtime#removeShutdownHook
 */

class ApplicationShutdownHooks {
   
    /* The set of registered hooks */
    private static IdentityHashMap<Thread, Thread> hooks;
    static {
   
        try {
   
            Shutdown.add(1 /* shutdown hook invocation order */,
                false /* not registered if shutdown in progress */,
                new Runnable() {
   
                    public void run() {
   
                        runHooks();
                    }
                }
            );
            hooks = new IdentityHashMap<>();
     
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值