ShutdownHook

在看源码时,发现了 Runtime.getRuntime().addShutdownHook 的用法,看起来是在jvm退出前做了一些清理工作

Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                LOGGER.info("shut down cat client in runtime shut down hook!");
                shutdown();
            }
        });

抱着好奇的心态看了下addShutdownHook源码,结合方法描述总结如下:

这是注册一个虚拟机的shutdown hook

1. JVM 虚拟机会对以下两种情况下的shuts down 事件作出响应:

        程序正常退出 - exit

        也就是最后一个非守护线程退出或者调用了System.exit 方法退出

        虚拟机由于被中断而退出 - terminated

        ctrl + c 或者 系统事件如 用户登出(user logoff) 或者 系统shutdown (system shutdown)

2. 不建议在shutdown hooks 中运行耗时长的任务(long-running),任务最好能快速的运行完

       当程序退出时,期望虚拟机也能及时的shutdown and exit

      当虚拟机由于用户登出或者系统shutdown 而退出(terminated)时,底层操作系统可能只允许一个固定的时间(a fixed amount of time)来shutdown and exit

3. 在极少数情况下,虚拟机有可能会终止(abort),在这种情况下不会保证shutdown hooks是否会被执行

     这里的abort 指的是虚拟机由于外部的信号而退出,比如unix的signal或者windows中的 TerminateProcess

4. 注册的hooks会并发的无序执行

 调用ApplicationShutdownHooks.add方法,注册hook,当程序退出时,jvm 调用runHooks方法,并发的执行所有hook线程,直到所有线程执行完毕后退出

public void addShutdownHook(Thread hook) {
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(new RuntimePermission("shutdownHooks"));
        }
        //调用add方法,将任务加入内存
        ApplicationShutdownHooks.add(hook);
    }

ApplicationShutdownHooks

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是一个map  IdentityHashMap<Thread, Thread> hooks
        hooks.put(hook, hook);
    }
    
    //执行hooks
    static void runHooks() {
        Collection<Thread> threads;
        synchronized(ApplicationShutdownHooks.class) {
            threads = hooks.keySet();
            hooks = null;
        }
        // 并发的执行hook
        for (Thread hook : threads) {
            hook.start();
        }
        //直到所有的线程执行完退出
        for (Thread hook : threads) {
            try {
                hook.join();
            } catch (InterruptedException x) { }
        }
    }

 

posted @ 2018-11-29 23:15  冰河世纪-dhy  阅读(535)  评论(0编辑  收藏  举报