Saturday, October 24, 2015

JVM ShutdownHook



http://blog.csdn.net/tiwerbao/article/details/8933147
Runtime.getRuntime().addShutdownHook(new MyShutdownHook());  
http://blog.csdn.net/tiwerbao/article/details/8933157
主要通过java.lang.Shutdown和java.lang.ApplicationShutdownHooks 这两个工具类来实现。Shutdown负责触发钩子,而ApplicationShutdownHooks负责维护钩子。
Shutdown
  1. private static final int RUNNING = 0;  
  2. private static final int HOOKS = 1;  
  3. private static final int FINALIZERS = 2;  
  4. private static int state = RUNNING; 
Shutdown初始定义了一个Runnable数组hooks,其中每个元素代表一个关闭钩子类型,
  1. private static final int MAX_SYSTEM_HOOKS = 10;  
  2. private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS];  
执行关闭钩子,是在JVM的关闭事件触发之后。通常是下面两种情况:
A Runtime.exit(),这时候会调用Shutdown.exit();
B JNI来DestroyJVM,这时候会调用Shutdown.shutdown();
    这两个方法,最后都会调用Shutdown.sequence()来触发关闭钩子和停止JVM。
  1. private static void sequence() {  
  2.         synchronized (lock) {  
  3.             if (state != HOOKS) return;  
  4.         }  
  5.         runHooks();          // 执行关闭钩子  
  6.         boolean rfoe;  
  7.         synchronized (lock) {  
  8.             state = FINALIZERS;  
  9.             rfoe = runFinalizersOnExit;  
  10.         }  
  11.         if (rfoe) runAllFinalizers();         // 全面停止系统  
  12. }  
执行关闭钩子,遍历hooks,把所有类型的钩子都run()起来。
  1. private static void runHooks() {  
  2.         for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {  
  3.             try {  
  4.                 Runnable hook;  
  5.                 synchronized (lock) {  
  6.                     currentRunningHook = i;  
  7.                     hook = hooks[i];  
  8.                 }  
  9.                 if (hook != null) hook.run();  
  10.             } catch(Throwable t) {}  
  11.         }  

java.lang.ApplicationShutdownHooks

用户等级的关闭钩子由ApplicationShutdownHooks来存放和维护。
在ApplicationShutdownHooks中,通过一个Map属性hooks来保存用户的关闭钩子。实际上每个关闭钩子都是一个线程,当JVM关闭事件触发的时候,就会执行钩子逻辑。
  1. private staticIdentityHashMap<Thread, Thread> hooks;  
这里使用IdentityHashMap来储存,这个map的key只比较地址,确保钩子的唯一性。即使两个对象属性完全一样,这里也会当成两个hook来处理
在ApplicationShutdownHooks加载的时候,首先会往Shutdown中add一个应用类型(1)的钩子类型线程,然后把 执行钩子逻辑的runHooks() 放入run()中等待调用。
这里ApplicationShutdownHooks为什么不实现Runnable接口,然后直接把自己add到Shutdown中呢?   因为没有必要:
因为Shutdown只关心用户的钩子,而对维护者ApplicationShutdownHooks没有兴趣,基于安全或者使用来考虑,都没有必要把ApplicationShutdownHooks整个传进去。所以这里新建一个线程,只把 runHooks()的调用 放进去,足矣。
这样一来,ApplicationShutdownHooks就不用实例化,可以做成单例,彻底变成了一个工具类,只用适度地暴露一些工具方法即可,并且通过静态属性hooks来保存钩子。 
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<>();
        } catch (IllegalStateException e) {
            // application shutdown hooks cannot be added if
            // shutdown is in progress.
            hooks = null;
        }

    }

    private ApplicationShutdownHooks() {}
    /* Iterates over all application hooks creating a new thread for each
     * to run in. Hooks are run concurrently and this method waits for
     * them to finish.
     */
    static void runHooks() {
        Collection<Thread> threads;
        synchronized(ApplicationShutdownHooks.class) {
            threads = hooks.keySet();
            hooks = null;
        }

        for (Thread hook : threads) {
            hook.start();
        }
        for (Thread hook : threads) {
            try {
                hook.join();
            } catch (InterruptedException x) { }
        }

    }

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts