2

我正在运行一个使用带有-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)
4

3 回答 3

3

更多细节,因为关于信号链的文档有点稀疏:

Java VM(至少是Oracles 实现,还包括OpenJDK)使用POSIX 信号进行内部通信,因此它安装了信号处理程序,例如SIGSEGV。这意味着,为了正常工作,Java VM 必须获取并检查进程中发生的任何 SIGSEGV,以区分“通信”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

于 2015-02-11T10:28:48.023 回答
2

由于您的问题似乎很有趣,因此我进行了快速谷歌搜索,并找到了有关 JNA 的页面。引用它

虚拟机崩溃保护

在定义新库和编写测试时遇到导致 VM 崩溃的内存访问错误的情况并不少见。这些通常是由不正确的映射或传递给本机库的无效参数引起的。要生成 Java 错误而不是使 VM 崩溃,请调用 Native.setProtected(true)。并非所有平台都支持这种保护;如果不是,Native.isProtected() 的值将保持为 false。注意:启用保护模式后,您应该使用 jsig 库(如果可用)(请参阅信号链)以避免干扰 JVM 对信号的使用。简而言之,在启动 Java 之前,将环境变量 LD_PRELOAD(或 LD_PRELOAD_64)设置为 JRE lib 目录(通常为 ${java.home}/lib/${os.arch}/libjsig.so)中 libjsig.so 的路径应用。

因此,据我猜测,jsig 库应该在您的 Java 安装目录中的“某处”可用。

于 2013-04-03T15:34:52.660 回答
1

jsig 库执行信号链接,允许将信号传递给 JVM。 从 IBM 看到这个

这很重要,因为根据我对 JVM 的理解,它使用 SIGSEGV 信号来确定您是否取消引用空指针,如果是,它将抛出 NullPointerException。

不幸的是,我不记得我从哪里获得了 libjsig.so 的副本,但您应该能够从一些 Red Hat 或 Debian 源中获得它。

于 2013-04-03T15:32:58.043 回答