/** * 添加新的shutdown,检查状态和配置 * * 除了注册DeleteOnExitHook的时侯,registerShutdownInProgress 参数默认设为false * application shutdown hooks 在运行中的时候,可能会向DeleteOnExitHook添加文件 * File.deleteOnExit() 会调用 DeleteOnExitHook.add(path); * * @params slot 退出钩子的索引位置, 在shutdown期间按顺序执行 * @params registerShutdownInProgress true to allow the hook * to be registered even if the shutdown is in progress. * @params hook the hook to be registered * * @throw IllegalStateException * if registerShutdownInProgress is false and shutdown is in progress; or * if registerShutdownInProgress is true and the shutdown process * already passes the given slot */ staticvoidadd(int slot, boolean registerShutdownInProgress, Runnable hook){ synchronized (lock) { if (hooks[slot] != null) thrownew InternalError("Shutdown hook at slot " + slot + " already registered");
if (!registerShutdownInProgress) { if (state > RUNNING) thrownew IllegalStateException("Shutdown in progress"); } else { // 1. 已经执行完了hook 阶段 // 2. 还在处理hook阶段,但是已经处理完了这个slot if (state > HOOKS || (state == HOOKS && slot <= currentRunningHook)) thrownew IllegalStateException("Shutdown in progress"); }
/* 被Runtime.exit()调用, 或者被系统终止事件handler调用。 */ staticvoidexit(int status){ boolean runMoreFinalizers = 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) { // 非0状态立即停止 halt(status); } else { // 兼容旧逻辑,执行finalizer后退出 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); } }
/* 通过JNI 调用 * 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. */ 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(); } } }
shutdown的字段state的状态机如下图所示:
graph LR
id0((begin))-->id1(running)
id1-->|"Runtime.exit()"|id2(HOOKS)
id1-->|"shutdown()"|id2
id2-->|"sequence()"|id3(FINALIZERS)
id3-->id4((end))
classDeleteOnExitHook{ privatestatic LinkedHashSet<String> files = new LinkedHashSet<>(); static { // DeleteOnExitHook 必须是最后一个被调用的shutdown hook。 // Application shutdown hooks 可能会向 delete on exit file list中添加文件, // 此时shutdown的状态是 hooks, 所以将 registerShutdownInProgress 设置为 true. sun.misc.SharedSecrets.getJavaLangAccess() .registerShutdownHook(2/* Shutdown hook invocation order */, true/* register even if shutdown in progress */, new Runnable() { publicvoidrun(){ runHooks(); } } ); }
privateDeleteOnExitHook(){}
staticsynchronizedvoidadd(String file){ if(files == null) { // DeleteOnExitHook is running. Too late to add a file thrownew IllegalStateException("Shutdown in progress"); }
ArrayList<String> toBeDeleted = new ArrayList<>(theFiles);
// reverse the list to maintain previous jdk deletion order. // Last in first deleted. Collections.reverse(toBeDeleted); for (String filename : toBeDeleted) { (new File(filename)).delete(); } } }