jvm关闭

本文详细介绍了Java JVM的关闭方式,包括正常关闭和强制关闭,重点关注关闭钩子(Shutdown Hook)的配置、调用流程及其实现原理。在正常关闭过程中,JVM会调用所有注册的关闭钩子,而强制关闭则不会执行钩子。关闭钩子的添加、管理和执行在Runtime和Shutdown类中实现,确保在特定条件下执行应用的清理工作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关闭方式

正常关闭

  • 最后一个普通线程(非守护线程)结束
  • 调用了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<>();
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值