* Wait for all non-daemon threads to end, then destroy the VM.
* This will actually create a trivial new Java waiter thread named “DestroyJavaVM”, but this will be seen as a different thread from the one that executed main, even though they are the same C thread. This allows mainThread.join( ) and mainThread.isAlive() to work as expected.
/* Invoked by the JNI DestroyJavaVM procedure when the last non-daemon thread has finished. * Unlike the exit method, this method does not actually halt the VM. * 译文:当最后一个非守护线程执行完成时,由JNI DestroyJavaVM过程调用。与exit方法不同的是,此方法实际上不会停止虚拟机。 */ staticvoidshutdown() { synchronized (lock) { switch (state) { case RUNNING: /* Initiate shutdown */ state = HOOKS; break; case HOOKS: /* Stall and then return */ case FINALIZERS: break; } } synchronized (Shutdown.class) { sequence(); } }
/* The actual shutdown sequence is defined here. * * If it weren't for runFinalizersOnExit, this would be simple -- we'd just * run the hooks and then halt. Instead we need to keep track of whether * we're running hooks or finalizers. In the latter case a finalizer could * invoke exit(1) to cause immediate termination, while in the former case * any further invocations of exit(n), for any n, simply stall. Note that * if on-exit finalizers are enabled they're run iff the shutdown is * initiated by an exit(0); they're never run on exit(n) for n != 0 or in * response to SIGINT, SIGTERM, etc. * 译文: 实际的关闭顺序在这里定义。 * 如果没有runFinalizersOnExit,这将是简单的——我们只需运行钩子,然后停止。相反,我们需要跟踪运行的是钩子还是终结器。 * 在后一种情况下,终结器可以调用exit(1)来导致立即终止,而在前一种情况下,任何对exit(n)的进一步调用,对于任何n, * 都只是暂停。注意,如果启用了on-exit终结器,那么如果关闭由一个exit(0)启动,它们就会运行;它们永远不会在退出(n)时运行, * 因为n != 0或响应SIGINT、SIGTERM等。 */ privatestaticvoidsequence() { synchronized (lock) { /* Guard against the possibility of a daemon thread invoking exit * after DestroyJavaVM initiates the shutdown sequence */ if (state != HOOKS) return; } runHooks(); // 核心 -- 执行钩子 boolean rfoe; synchronized (lock) { state = FINALIZERS; rfoe = runFinalizersOnExit; } if (rfoe) runAllFinalizers(); }
/* 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. * 译文: 遍历所有应用程序钩子,为每个要运行的钩子创建一个新线程。钩子任务是并发执行的,这个方法等待它们完成。 */ staticvoidrunHooks() { Collection<Thread> threads; synchronized(ApplicationShutdownHooks.class) { threads = hooks.keySet(); hooks = null; }
/* Invoked by Runtime.exit, which does all the security checks. * Also invoked by handlers for system-provided termination events, * which should pass a nonzero status code. */ staticvoidexit(int status) { booleanrunMoreFinalizers=false; synchronized (lock) { if (status != 0) runFinalizersOnExit = false; switch (state) { case RUNNING: /* Initiate shutdown */ state = HOOKS; break; case HOOKS: /* Stall and halt */ break; case FINALIZERS: // 如果是终结器 if (status != 0) { /* Halt immediately on nonzero status */ halt(status); // 关闭JVM } else { /* Compatibility with old behavior: * Run more finalizers and then halt */ runMoreFinalizers = runFinalizersOnExit; } break; } } if (runMoreFinalizers) { runAllFinalizers(); halt(status); } synchronized (Shutdown.class) { /* Synchronize on the class object, causing any other thread * that attempts to initiate shutdown to stall indefinitely */ sequence(); // 顺序关系方法,又回到上述正常关闭时执行钩子方法的逻辑了 halt(status); } }
Hello World!!! Exception in thread "main" java.lang.ArithmeticException: / by zero at com.maple.system.Demo_System_Exit.main(Demo_System_Exit.java:17) Hook Method...
/* The halt method is synchronized on the halt lock * to avoid corruption of the delete-on-shutdown file list. * It invokes the true native halt method. */ staticvoidhalt(int status) { synchronized (haltLock) { halt0(status); } }