Shutdown 源码阅读
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 源码阅读的更多相关文章
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- ThreadPoolExecutor 源码阅读
目录 ThreadPoolExecutor 源码阅读 Executor 框架 Executor ExecutorService AbstractExecutorService 构造器 状态 Worke ...
- 【详解】ThreadPoolExecutor源码阅读(二)
系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) AQS在W ...
- 【详解】ThreadPoolExecutor源码阅读(一)
系列目录 [详解]ThreadPoolExecutor源码阅读(一) [详解]ThreadPoolExecutor源码阅读(二) [详解]ThreadPoolExecutor源码阅读(三) 工作原理简 ...
- Caddy源码阅读(二)启动流程与 Event 事件通知
Caddy源码阅读(二)启动流程与 Event 事件通知 Preface Caddy 是 Go 语言构建的轻量配置化服务器.https://github.com/caddyserver/caddy C ...
- Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析
一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...
- 【原】FMDB源码阅读(三)
[原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...
- 【原】FMDB源码阅读(二)
[原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
随机推荐
- 关于php 7.4编译安装
一个不错的文章 https://hqidi.com/150.html 贴个地址就好啦, 借鉴了一把,很良心
- 【2017-05-04】winfrom进程、线程、用户控件
一.进程 一个进程就是一个程序,利用进程可以在一个程序中打开另一个程序. 1.开启某个进程Process.Start("文件缩写名"); 注意:Process要解析命名空间. 2. ...
- Beta冲刺版本第三天
该作业所属课程:https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass2 作业要求地址:https://edu.cnblogs.com ...
- sql 新增一个不为空的列
ALTER TABLE dbo.FW_PATROL_TASK ADD CRUISE_TYPE INT; UPDATE FW_PATROL_TASKSET CRUISE_TYPE = 0; --设置新列 ...
- Twitter的支撑架构:扩展网络与存储并提供服务——架构原则:一次性将事情做对,NFL原则 LSM+B+存储替代cassandra
Twitter工程团队近期提供了Twitter核心技术的演进和扩展的详细资料,这些核心技术支撑了Twitter自营数据中心的系统架构,用于提供社会媒体服务.他们分享的关键经验包括:超越原始规格和需求进 ...
- pip安装第三方库时提示No Module named pip
因为多次卸载/安装python不同版本导致出现pip模块不存在的问题,原因可能是环境没有配置好执行下面命令 ----完成
- Vue 实现 登陆后打开主页面(登陆组件 + 主页面组件)
本次演示,项目所需iview,router 首先 在 views 目录 新建 两个 组件 ( login.vue ,index.vue ) login.vue <template> < ...
- java两个实体公共属性赋值方法
model1 info=new model1();info.setAge("123");info.setCode("1234");info.setName(&q ...
- 题解 【ZJOI2009】 假期的宿舍
题面 解析 这其实就是个二分图匹配的水题(虽然我还是爆零了) 这题的意思就是说,有x个人,y张床(x,y不确定), 每个人只能睡在指定的几张床上, 问能否使每人都有床睡. 所以,直接二分图匹配,看最大 ...
- BZOJ 1778: [Usaco2010 Hol]Dotp 驱逐猪猡 概率与期望+高斯消元
这个还挺友好的,自己相对轻松能想出来~令 $f[i]$ 表示起点到点 $i$ 的期望次数,则 $ans[i]=f[i]\times \frac{p}{q}$ #include <cmath> ...