在 Windows 上尝试在 Hotspot JVM 中处理 SIGBREAK 时出现 IllegalArgumentException

IllegalArgumentException when trying to handle SIGBREAK in Hotspot JVM on Windows

我正在尝试使用 sun.misc 包中的信号处理 类(如记录 here)在 Windows 上的 Hotspot JVM 中处理 SIGBREAK 所以我可以在 Ctrl+Break 上触发关闭,而不仅仅是转储线程。但是,我 运行 遇到这样一种情况,它抛出一个 IllegalArgumentException 说 SIGBREAK 已经被 OS 或当我尝试设置处理程序时的 VM 处理。即使我 运行 带有 -Xrs 标志的 JVM 也会发生这种情况,该标志可能会禁用对 SIGBREAK 信号的处理。

有没有人有使用 sun.misc.Signal on Windows 处理信号的经验?有解决办法吗?

这似乎是一个相当混乱的话题。

documentation of the java launcher 指定:

When the -Xrs option is used, the JVM does not install a console control handler, implying that it does not watch for or process CTRL_C_EVENT, CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, or CTRL_SHUTDOWN_EVENT.

请注意 CTRL_BREAK_EVENT 不在列表中。所以它确实不受此选项的影响,但奇怪的是,文档声称指定 -Xrs 将暗示“Ctrl + Break thread dumps are not available”,当这个功能完全不受影响。

此外,其含义与 reader 的预期完全相反。当 JVM 不监听这些事件时,由于 -Xrs 选项,它不能将它们转发到 Java 侧处理程序,换句话说, 不是 支持为它们注册信号处理程序。这可以通过尝试为受该选项影响的信号安装信号处理程序来轻松测试,INT and/or TERM,它仅在 -Xrs 时有效未 指定。

通过调查 the code that tries to install a signal handler:

long oldH = handle0(sig.number, newH);
if (oldH == -1) {
    throw new IllegalArgumentException
        ("Signal already used by VM or OS: " + sig);
}

我们看到各种故障的通用答案是-1,所以我们不应该把异常消息“信号已经被VM使用或OS”理解得太字面意思。在这个地方,没有空间报告不同的原因,比如“无法安装处理程序,因为 JVM 不会由于 -Xrs 选项安装那种处理程序”。

据我所知,-Xrs 选项应该允许 本机代码 在较低级别安装信号处理程序,而无需 JVM 干扰,不为 Java 端 sun.misc.Signal 处理提供信号。

关于SIGTERM的问题,似乎整个文档与现实不同步。在我的测试中,指定 -Xrs 的最后一个 JVM 确实使 CTRL+BREAK 线程转储不可用,是 Java 6. 但是,如上所述,结果是该信号可用于本机代码,导致在没有此类处理程序的情况下中止,而不是使其可用于 sun.misc.Signal。即使在该 JVM 下,也无法为 SIGBREAK 安装 SignalHandler,无论 -Xrs 选项是否存在。