我正在调查Red Hat Linux上的Java问题(使用IBM JVM 1.4.2 64位).我想知道是否有人之前看过这个错误消息,并知道是否有解决此问题的方法?
资源:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class SignalTest extends Thread
{
private static Signal signal = new Signal("INT");
private static ShutdownHandler handler = new ShutdownHandler();
private static class ShutdownHandler implements SignalHandler
{
public void handle(Signal sig)
{
}
}
public static void main(String[] args)
{
try
{
Signal.handle(signal, handler);
}
catch(Throwable e)
{
e.printStackTrace();
}
try { Thread.sleep(5000); } catch(Exception e) { e.printStackTrace(); }
System.exit(0);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
java.lang.IllegalArgumentException <Signal already used by VM: INT>
java.lang.IllegalArgumentException: Signal already used by VM: INT
at
com.ibm.misc.SignalDispatcher.registerSignal(SignalDispatcher.java:145)
at sun.misc.Signal.handle(Signal.java:199)
at xxx
Run Code Online (Sandbox Code Playgroud)
附加信息:
我发现了一些奇怪的东西.它失败的原因是因为我在shell脚本中运行程序作为后台进程.
即sigtest.sh:
#!/bin/bash
java -cp . SignalTest >> sigtest.log 2>&1 &
Run Code Online (Sandbox Code Playgroud)
如果我从命令行运行程序,或删除"&"(即使它成为shell脚本中的前台进程),它没有问题......我不明白为什么会这样.
这很可能是 JVM 实现特定的问题。我们正在使用未记录/不受支持的 API ( sun.misc.Signal/SignalHandler),因此不保证 API 行为的合同。
IBM JVM 实现可能会以与 SUN JVM 实现不同的方式执行与信号处理相关的操作,从而导致此问题。因此,这个特定用例可以在 SUN JVM 中运行,但不能在 IBM JVM 中运行。
但请尝试以下操作(我自己无法尝试):
使用其中一个/两个/三个参数以及可能的值组合来启动 JVM,执行所有组合。
-Xrs指定/未指定的选项ibm.signalhandling.sigint设置为true/falseibm.signalhandling.rs设置为true/false(通过谷歌在几个错误转储中找到的属性,但我找不到关于它们的任何具体文档)
我不知道 IBM JVM 是否也支持这个特殊标志,但你也可以尝试添加这个,在 SUN JVM 中,它似乎专门针对 linux/solaris 下信号处理程序的一些问题
-XX:-AllowUserSignalHandlers
Run Code Online (Sandbox Code Playgroud)
或者尝试使用本机信号处理程序(如果您可以选择)。查看提供的代码示例:
尽管它与您的具体问题无关,但有关 JVM 信号处理的 IBM 文章(稍微过时,但仍然大部分正确)。使用本机代码信号处理程序的示例:
但我猜这一切可能都无济于事,因为 IBM JVM 实现可能依赖于处理SIGINT自身才能正确运行,因此永远不会给您处理自己的机会SIGINT。
顺便提一句。从描述到-Xrs标志,我知道它实际上可能会妨碍您做您想做的事。它说
当
-Xrs在Sun的JVM上使用时,JVM不会更改SIGINT、SIGTERM、SIGHUP和SIGQUIT的信号掩码,并且不会安装这些信号的信号处理程序 。
或者,这可能意味着仅不执行信号的 JVM 默认操作。或者它可能取决于 JVM 实现的真正含义。