更多细节,因为关于信号链的文档有点稀疏:
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