我正在调查 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);
    }
}

输出:

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

附加信息:

我发现了一些奇怪的事情。它失败的原因是因为我在 shell 脚本中作为后台进程运行该程序。

IE。sigtest.sh:

#!/bin/bash
java -cp . SignalTest >> sigtest.log 2>&1 &

如果我从命令行运行程序,或者删除“&”(即使它成为 shell 脚本中的前台进程),它没有问题......我不明白为什么会这样。

有帮助吗?

解决方案

这很可能是一个JVM执行情况的具体问题。我们使用无证件/不支持API(sun.misc.Signal/SignalHandler),因此没有合同上的行为API保证。

IBM JVM执行能做信号处理相关的事情以不同的方式从太阳JVM执行情况和由此引起这个问题。因此,这个具体使用情况工作在太阳JVM但不是在IBM JVM。

但是,尝试以下(我不能试用我自己):

做所有的组合开始JVM一/两个/三的那些参数的有可能值的组合。

  1. -Xrs 选择指定/不定
  2. 酒店 ibm.signalhandling.sigint 设置 true / false
  3. 酒店 ibm.signalhandling.rs 设置 true / false

(属性在哪里找到通过谷歌在几个错误堆放场但我不能找到任何具体的文档在他们身上)

我不知道IBM JVM也支持这种特殊标志但是你可以试试加入这个过其在太阳JVM似乎是特定的一些问题与信号处理程序下linux/solaris

-XX:-AllowUserSignalHandlers

或试图使用一个当地信号处理程序,如果这是一个选择。检查代码样本提供:

虽然它并不涉及到你的具体问题,IBM条JVM信号处理(有点过时但仍然主要是正确的)。有样本机代码信号处理程序:

启示Java信号处理和终止


但我猜这可能是没有效果如IBM JVM执行可以依靠的处理 SIGINT 本身作正常并因此而永远不会给你一个机会,来处理 SIGINT 你自己。

顺便说一句.从 介绍来的 -Xrs 标志 我的理解是,它实际上可能会妨碍你做你想要什么。它说的

-Xrs 上使用太阳的JVM, 信号遮罩信号情报,SIGTERM, SIGHUP,并SIGQUIT都不改变 JVM, 信号处理程序对于这些 信号不是安装了.

或者,它可能意味着,只有JVM默认的行动的信号不是执行。或者,它可能取决于JVM执行什么是真正的意思。

其他提示

尝试使用 -Xrs 选项启动 JVM,该选项在 IBM JVM 上有效,根据 反正。这可能会阻止冲突。

编辑:为了满足您的潜在愿望,请查看:

Runtime.getRuntime().addShutdownHook(线程)

您对线程对象进行子类化,它将作为关闭的一部分启动(取出 -Xrs 以便它可以正常工作)。有些事情(例如在运行时调用暂停)可以阻止这种情况发生,因此您确实需要意识到这种情况最终不会发生的可能性。

作为写亨氏Kabutz ,则能够赶上信号取决于您正在运行的操作系统和propably的JVM版本。如果某个OS / JVM组合不会让你注册你的信号,那么你的运气了。也许与OS / VM设置调整可能的帮助。

根据您的意见,增加了关闭挂钩提议伊沙伊应该做的特技。

发生异常,因为VM已经到位为SIGINT的信号处理程序。你能/应该做这取决于在此抛出异常的上下文。

我试过相同的代码,它为我工作。所以我猜有可能是在设置一些差异。

添加后

System.out.println("Hello");

到手柄消息我可以运行这样的类:

z@zolty:/tmp/so$ java SignalTest & sleep 1s && kill -2 $!
[1] 20467
z@zolty:/tmp/so$ Hello
z@zolty:/tmp/so$
z@zolty:/tmp/so$ java SignalTest
[1]+  Done             java SignalTest

我这通过使用不同的JVM实现(SUSE)工作,而不是IBM。 当未记录的功能处理,似乎JVM不是在行为上非常一致。

我也有同样的问题。我跑从KSH脚本的Java程序。 如果我的帐户运行脚本有CSH轮廓 即,/ etc / passwd文件

用户X:*:7260:20 :: /家/用户X:在/ usr / bin中/ CSH

该脚本将成功地运行。但是,如果我与帐户运行它具有比SH轮廓其他,这是给同样的错误。

因此,解决的办法是让你的UNIX用户的个人资料变更为CSH。

我也与IBM JVM(64位)在Linux遇到了这个问题。原来,在JVM是调用它的过程的信号掩码敏感。

> grep Sig /proc/self/status
SigQ:   1/1030663
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000001001006
SigCgt: 0000000000000000

请注意,对于SIGINT(值2)的比特中SigIgn被设置。当使用这种面膜启动IBM JVM,它拒绝安装SIGINT的处理程序。我工作围绕这一问题通过了SIGINT处理程序重置为默认一个Python包装启动JVM:

#!/usr/bin/env python

import os
import signal
import sys

signal.signal(signal.SIGINT, signal.SIG_DFL)

args = sys.argv[1:]
os.execv(args[0], args)

的第一个参数的包装是java命令,然后按照参数为JVM。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top