[讨论] [HotSpot VM] JVM是否主动抛出各种系统信号用来实现某些逻辑?如SIGSEGV

qianhd 2014-11-13
最近用JNA来调用一个C++开发的动态库,这个库中为了便于调试,注册监听了系统信号,在收到信号之后,打印出堆栈信息,并kill掉自己。(因为发现信号被handler处理过一次,系统就不处理了。只能主动再触发一次)

用JNA调用后,随机性的出现各种coredump,堆栈是各种各样,原因也各种各样,有sigsegv(0),有sigpwr,看起来绝对不是程序有问题导致的。(因为JVM的err文件中每次都不同,我就不贴了)

网上搜了一下,JVM确实是有监听这些信号。
但我想知道JVM会抛出这些信号吗?比如用信号来处理某些GC逻辑。

以下这3个JVM参数跟这个问题有关系吗?
ReduceSignalUsage
AllowUserSignalHandlers
UseSignalChaining



@RednaxelaFX 指点一下
qianhd 2014-11-13
http://www.oracle.com/technetwork/java/javase/signals-139944.html#gbzcj

看起来是踩到了坑里面去了
看描述JVM会用这些信号来做null check。明天试下-Xrs

引用

SIGSEGV, SIGBUS, SIGFPE, SIGPIPE, SIGILL, SIGQUIT

Used in the implementation for implicit null check, and so forth.

Thread dump support: To dump Java stack traces at the standard error stream. (Optional.)


引用

SIGTERM, SIGINT, SIGHUP

Used to support the shutdown hook mechanism ( java.lang.Runtime.addShutdownHook) when the VM is terminated abnormally. (Optional.)




RednaxelaFX 2014-11-14
嗯有文档就是好。

HotSpot VM有若干内部操作再Posix上是通过信号来处理的,不能关掉。

有这么几类:

1、隐式异常处理
(1) 隐式空指针检查(implicit null check) - SIGSEGV
(2) 隐式栈溢出检查(stack banging) - SIGSEGV(Mac OS X上也可能是SIGBUS)
(3) 除以0异常(divide by zero) - SIGFPE

2、Safepoint轮询(safepoint polling) - SIGSEGV

参考JVM_handle_linux_signal()里的处理。

有些对SIGBUS的处理是防御性的,例如用Unsafe访问memory mapped file可能会SIGBUS,而HotSpot VM不想因此crash掉所以也做了防御性处理。

其它有些外围功能是用信号来允许用户与程序交互。例如向HotSpot VM发送 SIGQUIT 可以触发打印stack trace。这些是可以关掉的。-Xrs可以减少VM内对信号的使用,把JVM外围可关闭的信号处理关掉。
qianhd 2014-11-14
我看文档上介绍, Option的不是可以关的吗?
就在那个表格的上方


The following table lists the signals that are currently used on Solaris OS and Linux. The mention “optional” means that the signal is not necessary when the -Xrs option is specified, as explained in   6.1.1 Reducing Signal Usage. The mention “configurable” means that alternative signals may be specified, as explained in   6.1.2 Alternative Signals.


http://www.oracle.com/technetwork/java/javase/signals-139944.html#gbzcj

看起来
引用
(1) 隐式空指针检查(implicit null check) - SIGSEGV
这个应该是可以关掉的,
不过正如你说的, 有些信号是无法关闭的, 加上-Xrs依然会coredump, 或许只能在C++库中关闭掉backtrace, 或者加强backtrace的逻辑, 过滤掉jvm触发的各种信号.

这方面有经验分享下吗? 比如如何判断信号是不是jvm触发的? 还是只能从堆栈中判断?



RednaxelaFX 2014-11-14
qianhd 写道
我看文档上介绍, Option的不是可以关的吗?
就在那个表格的上方

Optional的是可以关掉。Implicit null check那个在第一行,没写optional。
第二行(SIGQUIT)开始才是optional的。

虽然有-XX:-ImplicitNullChecks的参数,但这不是product参数,对实际用户来说用不了。
我前面的回复里说的不能关闭的都肯定是不能关闭的。

qianhd 写道
不过正如你说的, 有些信号是无法关闭的, 加上-Xrs依然会coredump, 或许只能在C++库中关闭掉backtrace, 或者加强backtrace的逻辑, 过滤掉jvm触发的各种信号.

这方面有经验分享下吗? 比如如何判断信号是不是jvm触发的? 还是只能从堆栈中判断

参考JVM_handle_linux_signal()的实现。它很明确:看是什么signal,在什么pc发生,这个signal+pc的组合是不是JVM知道的地方,是的话处理,否则不管。
qianhd 2014-11-17
RednaxelaFX 写道

参考JVM_handle_linux_signal()的实现。它很明确:看是什么signal,在什么pc发生,这个signal+pc的组合是不是JVM知道的地方,是的话处理,否则不管。


搞定了~~通过判断触发的地址是不是在so的地址中来判断。
不过so的地址好像只能通过/proc/pid/maps或者maps -X pid来获得,
RednaxelaFX 2014-11-18
qianhd 写道
RednaxelaFX 写道

参考JVM_handle_linux_signal()的实现。它很明确:看是什么signal,在什么pc发生,这个signal+pc的组合是不是JVM知道的地方,是的话处理,否则不管。


搞定了~~通过判断触发的地址是不是在so的地址中来判断。
不过so的地址好像只能通过/proc/pid/maps或者maps -X pid来获得,

光看是不是在libjvm.so里还不太够吧。至少得把HotSpot VM的CodeCache范围也考虑进去,这是在heap里的一块r_x内存。
qianhd 2014-11-18
RednaxelaFX 写道
qianhd 写道
RednaxelaFX 写道

参考JVM_handle_linux_signal()的实现。它很明确:看是什么signal,在什么pc发生,这个signal+pc的组合是不是JVM知道的地方,是的话处理,否则不管。


搞定了~~通过判断触发的地址是不是在so的地址中来判断。
不过so的地址好像只能通过/proc/pid/maps或者maps -X pid来获得,

光看是不是在libjvm.so里还不太够吧。至少得把HotSpot VM的CodeCache范围也考虑进去,这是在heap里的一块r_x内存。


我只看地址是不是我提供的库里面的就行了啊。
是我提供的库里面触发的信号,才处理,其他信号我处理了也没用啊。
RednaxelaFX 2014-11-19
qianhd 写道
RednaxelaFX 写道
qianhd 写道
RednaxelaFX 写道

参考JVM_handle_linux_signal()的实现。它很明确:看是什么signal,在什么pc发生,这个signal+pc的组合是不是JVM知道的地方,是的话处理,否则不管。


搞定了~~通过判断触发的地址是不是在so的地址中来判断。
不过so的地址好像只能通过/proc/pid/maps或者maps -X pid来获得,

光看是不是在libjvm.so里还不太够吧。至少得把HotSpot VM的CodeCache范围也考虑进去,这是在heap里的一块r_x内存。


我只看地址是不是我提供的库里面的就行了啊。
是我提供的库里面触发的信号,才处理,其他信号我处理了也没用啊。

靠谱
Global site tag (gtag.js) - Google Analytics