发送 SIGTERM 时 VM_Exit 是如何传递给 VM Thread 的?谁来传递?
How is VM_Exit delivered to VM Thread when sending SIGTERM and who does the delivering?
我正在尝试了解 JVM 热点如何处理终止信号(例如 SIGTERM
)。我发现 SIGTERM
信号配置设置为 at this point 到 UserHandler
看起来像(省略注释):
static void UserHandler(int sig, void *siginfo, void *context) {
if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) {
return;
}
if (sig == SIGINT && VMError::is_error_reported()) {
os::die();
}
os::signal_notify(sig);
}
所以它所做的就是通知Signal Dispatcher
并将接收到的信号编号设置为static volatile jint pending_signals[NSIG+1]
。
但在 SIGTERM
的情况下,实际的 exit(143)
是在 VM Thread
中完成的。带有 _exit_code = 143
的 VM_Exit
任务以某种方式传递给 VM Thread
。
问题: 能否提示一下是谁生成了这个 VM_Exit
任务,之后又发给了 VM Thread
?我特别关心 143 如何设置为 VM_Exit::_exit_code
?
I 运行 gdb 下的 JVM HotSpot 主要有以下 class:
public class Main{
public static void main(String args[]) throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("Shutdown hook is called");
}));
Thread.sleep(1000000);
}
}
并没有发现 Signal Dispatcher
正在发送 VM_Exit
任务。终止发生在 that statement:
JavaCalls::call_virtual(&result,
threadObj, thread_klass,
vmSymbols::exit_method_name(),
vmSymbols::void_method_signature(),
THREAD);
SIGTERM
、SIGINT
和 SIGHUP
在 java.lang.Terminator
的 Java code 中处理。
async-profiler 的一个鲜为人知的特性是它可以分析任意本机函数并显示混合的 Java+本机堆栈。例如。如果你想拦截 JVM_Halt
并查看 Java 代码调用它,运行
$ java -agentpath:/path/to/libasyncProfiler.so=start,traces,threads,event=JVM_Halt Main
Started [JVM_Halt] profiling
^CShutdown hook is called
--- 1 events (100.00%), 1 sample
[ 0] JVM_Halt
[ 1] java.lang.Shutdown.halt0
[ 2] java.lang.Shutdown.halt
[ 3] java.lang.Shutdown.exit
[ 4] java.lang.Terminator.handle
[ 5] jdk.internal.misc.Signal.run
[ 6] java.lang.Thread.run
[ 7] [SIGINT handler tid=19080]
我正在尝试了解 JVM 热点如何处理终止信号(例如 SIGTERM
)。我发现 SIGTERM
信号配置设置为 at this point 到 UserHandler
看起来像(省略注释):
static void UserHandler(int sig, void *siginfo, void *context) {
if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) {
return;
}
if (sig == SIGINT && VMError::is_error_reported()) {
os::die();
}
os::signal_notify(sig);
}
所以它所做的就是通知Signal Dispatcher
并将接收到的信号编号设置为static volatile jint pending_signals[NSIG+1]
。
但在 SIGTERM
的情况下,实际的 exit(143)
是在 VM Thread
中完成的。带有 _exit_code = 143
的 VM_Exit
任务以某种方式传递给 VM Thread
。
问题: 能否提示一下是谁生成了这个 VM_Exit
任务,之后又发给了 VM Thread
?我特别关心 143 如何设置为 VM_Exit::_exit_code
?
I 运行 gdb 下的 JVM HotSpot 主要有以下 class:
public class Main{
public static void main(String args[]) throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("Shutdown hook is called");
}));
Thread.sleep(1000000);
}
}
并没有发现 Signal Dispatcher
正在发送 VM_Exit
任务。终止发生在 that statement:
JavaCalls::call_virtual(&result,
threadObj, thread_klass,
vmSymbols::exit_method_name(),
vmSymbols::void_method_signature(),
THREAD);
SIGTERM
、SIGINT
和 SIGHUP
在 java.lang.Terminator
的 Java code 中处理。
async-profiler 的一个鲜为人知的特性是它可以分析任意本机函数并显示混合的 Java+本机堆栈。例如。如果你想拦截 JVM_Halt
并查看 Java 代码调用它,运行
$ java -agentpath:/path/to/libasyncProfiler.so=start,traces,threads,event=JVM_Halt Main
Started [JVM_Halt] profiling
^CShutdown hook is called
--- 1 events (100.00%), 1 sample
[ 0] JVM_Halt
[ 1] java.lang.Shutdown.halt0
[ 2] java.lang.Shutdown.halt
[ 3] java.lang.Shutdown.exit
[ 4] java.lang.Terminator.handle
[ 5] jdk.internal.misc.Signal.run
[ 6] java.lang.Thread.run
[ 7] [SIGINT handler tid=19080]