我正在运行一个使用带有-Xcheck:jni
标志的JNI的Java程序,我收到的信息如下:
SIGSEGV: [libjvm.so+0x6fd190], sa_mask[0]=0x00000400, sa_flags=0x10000000, flags was changed from 0x10000004, consider using jsig library
这是什么意思?我应该担心吗?什么是jsig库?
我在Linux上使用Java 7,或者确切地说:
JRE version: 7.0_03-b04
Java VM: Java HotSpot(TM) 64-Bit Server VM (22.1-b02 mixed mode linux-amd64 compressed oops)
答案 0 :(得分:3)
更多细节,因为有关信号链的文档有点稀疏:
Java VM(至少是Oracles实现,也包括OpenJDK)使用POSIX信号进行内部通信,因此它安装了信号处理程序,例如:对于SIGSEGV。这意味着,为了正常工作,Java VM必须获取并检查过程中发生的任何SIGSEGV,以区分“通信”SIGSEGV和真正的程序错误。
但是信号处理程序是一个全局资源,在一个进程中,任何本机代码都可以安装信号处理程序并替换Java VM安装的代码。
-Xcheck:jni使VM运行定期检查,其中包括是否有人更改了Java VM下的信号处理程序。如果它检测到更改,则会输出警告。
为了解决这个问题(用户安装的信号处理程序取代JavaVM信号处理程序)并容纳可能有理由安装信号处理程序的用户代码,Java VM使用“信号处理”,这基本上意味着信号处理程序( VM和用户链接在一起:JavaVM信号处理程序首先运行;如果他们认为信号对VM不感兴趣,它会将信号传递给用户处理程序。
有两种方法可以激活此支持: 1)使用您自己的本机启动程序(一个加载libjvm.so的C程序,调用JNI_CreateJavaVM来创建VM等)。在这种情况下,如果启动程序在创建Java VM之前安装其用户信号处理程序,Java VM将记住用户处理程序并将它们链接在自己的信号处理程序后面。 2)如果在创建Java VM之后加载了用户本机代码,则这不起作用。 libjsig.so就是这个问题的答案:它用自己的版本替换系统信号API(sigaction()等),并且任何试图安装信号处理程序的用户代码都不会替换全局信号处理程序,但是用户处理程序将链接在(已安装的)Java VM信号处理程序后面。
为了使(2)工作,必须在启动VM之前使用LD_PRELOAD加载libjsig.so:
例如: LD_PRELOAD = // jre / lib / amd64 / libjsig.so java myprogram
答案 1 :(得分:2)
由于您的问题似乎很有趣,我进行了快速谷歌搜索并找到了that page concerning JNA。引用它
VM崩溃保护
定义新库并编写测试以遇到导致VM崩溃的内存访问错误并不罕见。这些通常是由不正确的映射或传递给本机库的无效参数引起的。要生成Java错误而不是崩溃VM,请调用Native.setProtected(true)。并非所有平台都支持这种保护;如果没有,Native.isProtected()的值将保持为false。 注意:启用保护模式后,您应该使用jsig库(如果可用)(请参阅Signal Chaining)以避免干扰JVM使用信号。简而言之,在启动Java之前,将环境变量LD_PRELOAD(或LD_PRELOAD_64)设置为JRE lib目录中的libjsig.so路径(通常是$ {java.home} / lib / $ {os.arch} /libjsig.so)应用
因此,从我猜开始,jsig库应该在Java安装目录中“某处”可用。
答案 2 :(得分:1)
jsig库确实发出信号链接信号,允许将信号传递给JVM。 See this from IBM
这很重要,因为从我对JVM的理解来看,它使用SIGSEGV信号来确定你是否取消引用空指针,如果你是,它会抛出一个NullPointerException。
不幸的是,我永远不会记得我从哪里获得了libjsig.so的副本,但你应该可以从Red Hat或Debian源代码中获取它。