[讨论] [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内存。 我只看地址是不是我提供的库里面的就行了啊。 是我提供的库里面触发的信号,才处理,其他信号我处理了也没用啊。 靠谱 |