Shutdown

/**
* 虚拟机关闭步骤
* @since 1.3
*/
class Shutdown {
/* 关闭状态 */
private static final int RUNNING = 0;
private static final int HOOKS = 1;
private static final int FINALIZERS = 2;
private static int state = RUNNING; /* Should we run all finalizers upon exit? */
private static boolean runFinalizersOnExit = false;
/**
* The system shutdown hooks are registered with a predefined slot.
* The list of shutdown hooks is as follows:
* (0) Console restore hook
* (1) Application hooks
* (2) DeleteOnExit hook
*/
// 最多可注册的钩子函数个数
private static final int MAX_SYSTEM_HOOKS = 10;
private static final Runnable[] hooks = new Runnable[MAX_SYSTEM_HOOKS]; // 当前运行钩子的索引
private static int currentRunningHook = 0; /* The preceding static fields are protected by this lock */
private static class Lock { };
private static Object lock = new Lock(); /* Lock object for the native halt method */
private static Object haltLock = new Lock(); /* Invoked by Runtime.runFinalizersOnExit */
static void setRunFinalizersOnExit(boolean run) {
synchronized (lock) {
runFinalizersOnExit = run;
}
} /**
* 添加一个关闭钩子
*
* @params slot 目标索引
* @params registerShutdownInProgress 是否允许在关闭过程中注册钩子
* @params hook 待注册的钩子
*/
static void add(int slot, boolean registerShutdownInProgress, Runnable hook) {
synchronized (lock) {
// 目标索引处已经注册了
if (hooks[slot] != null) {
throw new InternalError("Shutdown hook at slot " + slot + " already registered");
} if (!registerShutdownInProgress) {
if (state > RUNNING) {
throw new IllegalStateException("Shutdown in progress");
}
} else {
if (state > HOOKS || state == HOOKS && slot <= currentRunningHook) {
throw new IllegalStateException("Shutdown in progress");
}
}
// 写入钩子
hooks[slot] = hook;
}
} /**
* 运行所有注册的关闭钩子
*/
private static void runHooks() {
for (int i=0; i < MAX_SYSTEM_HOOKS; i++) {
try {
Runnable hook;
synchronized (lock) {
// acquire the lock to make sure the hook registered during
// shutdown is visible here.
currentRunningHook = i;
hook = hooks[i];
}
if (hook != null) {
hook.run();
}
} catch(final Throwable t) {
if (t instanceof ThreadDeath) {
final ThreadDeath td = (ThreadDeath)t;
throw td;
}
}
}
} /**
* 强制关闭虚拟机
*/
static void halt(int status) {
synchronized (haltLock) {
halt0(status);
}
} static native void halt0(int status); /* Wormhole for invoking java.lang.ref.Finalizer.runAllFinalizers */
private static native void runAllFinalizers(); /**
* 实际的关机顺序定义
*/
private static void sequence() {
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;
}
// 运行 Finalizers
if (rfoe) {
runAllFinalizers();
}
} /**
* Invoked by Runtime.exit, which does all the security checks.
*/
static void exit(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) {
/* Halt immediately on nonzero status */
halt(status);
} 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);
}
} /* 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.
*/
static void shutdown() {
// 修改状态
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 源码阅读的更多相关文章

  1. 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分

    这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...

  2. ThreadPoolExecutor 源码阅读

    目录 ThreadPoolExecutor 源码阅读 Executor 框架 Executor ExecutorService AbstractExecutorService 构造器 状态 Worke ...

  3. 【详解】ThreadPoolExecutor源码阅读(二)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...

  4. 【详解】ThreadPoolExecutor源码阅读(一)

    系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 工作原理简 ...

  5. Caddy源码阅读(二)启动流程与 Event 事件通知

    Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy C ...

  6. Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析

    一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...

  7. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  8. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  9. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

随机推荐

  1. angular实现对百度天气api跨域请求

    申请秘钥:http://lbsyun.baidu.com/apiconsole/key  ,有个百度账号就行ak=开发者秘钥 url地址  :http://api.map.baidu.com/tele ...

  2. Java学习笔记【二、标识符、关键字、数据类型】

    基础语法 大小写敏感 类名用帕斯卡命名法 方法名用驼峰命名法 所有java程序,源码文件名须与类名一致 所有java程序,均以 public static void main(string []arg ...

  3. MyBatis Generator 移除字段前缀

    在table标签内添加 <columnRenamingRule searchString="wrc_" replaceString=""/> < ...

  4. Liux chmod 给文件夹赋权限

    777 最高权限 给文件夹及子文件夹赋权限 chmod -R 777 * 给单独文件赋权限 chmod -R 777 ./startup.sh

  5. 块格式化上下文(Block Formatting Context,BFC)

    块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域. 下列方式会创建块格 ...

  6. loj2613 「NOIP2013」华容道[最短路]

    感觉和以前做过的一个推箱子很像,都是可以用bfs解决的,而且都是手玩出结论. 因为起始棋子肯定是要和空格交换的,所以第一件事是先把空格移到棋子旁边.然后讨论怎么设计搜索状态.由于和推箱子实在太像了,所 ...

  7. mysqldump --tab=path参数使用

    [root@zstedu tmp]# chown -R mysql. /tmp/andyxi3306/ [root@zstedu tmp]# mysqldump -h127.0.0.1 -uroot ...

  8. 多个Promise执行顺序

    app.isLogin() // 判断是否登录后 .then(res=>{ this.setData({ login: true }, res2=>{ // 清空临时积分 return a ...

  9. HDU-1358-Period(KMP, 循环节)

    链接: https://vjudge.net/problem/HDU-1358#author=0 题意: For each prefix of a given string S with N char ...

  10. Redis——解决“org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisReferenceResolver': Unsatisfied dependency expressed through constructor parameter 0”

    错误栈: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ...