25 关于 Signal Dispatcher
Posted 蓝风9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了25 关于 Signal Dispatcher相关的知识,希望对你有一定的参考价值。
前言
呵呵 最近看到一篇文章, [讨论] 通过kill -3 pid 来输出Thread Dump日志信息的时效性
呵呵 关于常见的几个线程 AttchListener, Signal Dispatcher, Reference Handler, Finalizer, 虽然 平时使用的不是很多吧, 但是 还是可以了解一下的
这里 我们便来看一下 Signal Dispatcher 这个线程吧
一下的相关代码, 截图如果没有特殊说明 基于 jdk9
测试用例
package com.hx.test05;
import sun.misc.Signal;
import sun.misc.SignalHandler;
/**
* SignalHandler
*
* @author Jerry.X.He <970655147@qq.com>
* @version 1.0
* @date 2020-05-05 10:53
*/
public class Test24SignalHandler
// Test24SignalHandler
public static void main(String[] args) throws Exception
Signal.handle(new Signal("ALRM"), new SignalHandler()
@Override
public void handle(Signal signal)
System.out.println(signal);
);
// 发送信号
// Signal.raise(new Signal("ALRM"));
System.in.read();
测试代码里面 给 ALRM 这个信号, 注册了一个 signalHandler
那么 怎么给 vm 发送信号呢?, 通过 kill 命令, kill -14 $pid, 14 号信号, 就是这里的 ALRM
然后 可以看到 经过 signalHandler 的业务处理, 控制台 输出了 这个信号的相关信息
Signal Dispatcher
我们来看一下 Signal Dispatcher 的初始化, 以及它 主要做的事情
这里创建了 java.lang.Thread 对象, 并添加到了 系统线程组 里面, 然后下面 还设置了 本地线程, 优先级, 守护线程 的相关配置
创建了一个 本地线程(C层面), 并将它们互相建立关系, 并启动线程
Signal Dispatcher 做的事情
可以看到 就是不断等待 信号过来, 然后进行处理
对于 SIGBREAK/SIGQUIT 信号, 特殊处理, 输出 堆栈信息, JNI信息, 死锁, 堆的信息 等等
对于 其他的 信号 将业务委托给 sun.misc.Signal
sun.misc.Signal
java 层面的这个 Signal 主要是维护了 Signal 和 java层面的 Signal.Handler 之间的关系, 另外的这个 signals 是辅助使用存放了 Signal 的 number 到 Signal 的映射
构造方法, 根据 Signal 的名字, 来查询对应的 Signal, 如果是 未注册的 Signal 抛出异常
注册 Signal 和 SignalHandler 的映射, 只保留 java 层面的 handler
发送一个信号, 更下面是直接 不同的平台 委托相关的函数发送信号
信号的处理, 根据 Signal 的 number 查询 Signal, 然后查询其 注册的 handler, 如果有 启动一个线程 来处理 handler 的业务
整理一下流程
1. 程序中注册了 SIGALRM -> alrmSignalHandler 的映射关系
2. 通过终端 kill 命令 或者 程序中 raise 发送信号
3. vm 里面 Signal Dispatcher 线程检测到这个信号, 因为不是 SIGBREAK/SIGQUIT, 所以 将信号委托给了 sum.misc.Signal 来处理
4. sum.misc.Signal 里面查询 SIGALRM 对应的 handler, handler 存在, 接下来新起一个 线程来处理 handler 的业务
以下运行时截图来自于 jdk8
Signal.name
呵呵 之前将 ALRM 传递为 SIGALRM, 结果在 jdk8 和 jdk9 里面都报错了
相信通过上面的 jdk9 的 Signal 的构造方法 你很清楚报错的原因是什么, 那么 jdk8 报错的原因呢?
做映射的 信号量名称 本身就没有 SIG 前缀
jdk9 的实现是这样子的, 构造方法中限定不能以 SIG 开头, vm 这一层 如果不以 SIG 开头, 添加上 SIG 前缀
HUB, INT, TERM 信号
在 System.initializeSystemClass 的时候 调用了 Terminator.setup
unix, 类unix 操作系统上面是这样
windows 操作系统上面是这样
注册了这几个信号的 signalHandler, 使用 Shutdown.exit 来关闭系统
Signal already used by VM or OS
mac, unix, 类unix 相关操作系统 上面是这样, 只是可能各个 平台 注册的忽略的信号量不一样
windows 上面是这样
返回 -1 的情况就回 抛出该异常
jdk9 上面 name 以 SIG 开头也会抛出该异常
完
参考
[讨论] 通过kill -3 pid 来输出Thread Dump日志信息的时效性
以上是关于25 关于 Signal Dispatcher的主要内容,如果未能解决你的问题,请参考以下文章
默认线程,如 DestroyJavaVM、Reference Handler、Signal Dispatcher
关于WARN Dispatcher:68 - Could not find action or result报错