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. List<int>转化为逗号链接的字符串

    /// <summary> /// List<int>转化为逗号链接的字符串 /// </summary> /// <param name="lis ...

  2. 十二,k8s集群访问控制之RBAC授权

    目录 角色访问控制RBAC (Role-Based Access Control) 常用的授权插件: RBAC控制: role 和 clusterrole rolebinding 和 clusterr ...

  3. pytest的使用

    一.python安装 1.windows(server): 双击python-3.6.7-amd64.exe执行安装流程,使用默认安装方式即可. 安装完成后查看是否安装成功: C:\Users\Adm ...

  4. Android异常与性能优化相关面试问题-冷启动优化面试问题详解

    什么是冷启动: 冷启动的定义:冷启动就是在启动应用前,系统中没有该应用的任何进程信息.实际也就是要执行Application.onCreate()方法的那次启动. 冷启动 / 热启动的区别:热启动:用 ...

  5. C#形参和实参、引用类型和值类型使用时的一个注意点。

    这是早上群里讨论的例子. static void main(string [] arg){ var p1=new Person{Name="张三"}; var p2=new Per ...

  6. HelloWorld编写过程中注意事项

    一.package关键字 * package表示当前代码所属的包(package),是一种组织结构.其他package通过包名调用这个包下内容* package是必须的,每个文件的package必须存 ...

  7. JavaScript对象原型

    一.MDN上的解释(有点抽象) 基于原型的语言? JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模 ...

  8. 本地文件上传到gitlab

    1.本地创建目录gbdt_model 2.进入文件目录,在文件中点击鼠标右键选择bash控制台进入 3.运行git init 命令,文件中会多出一个.git 命令 4. git commit -m & ...

  9. Spring事务源码分析

    首先看例子,这例子摘抄自开涛的跟我学spring3. @Test public void testPlatformTransactionManager() { DefaultTransactionDe ...

  10. Linux磁盘分区的实用管理命令

    系统环境:Centos6.7 命令信息: 1.lsblk  列出分区信息,可以查看分区的光在目录和使用情况  (读取内存中的分区表信息) 2.fdisk 用来创建MBR分区(也可以创建GPT分区,但是 ...