2009-06-26 3 views
5

Ich untersuche ein Java-Problem (mit IBM JVM 1.4.2 64-Bit) auf Red Hat Linux. Ich frage mich, ob jemand diese Fehlermeldung zuvor gesehen hat und weiß, ob es eine Problemumgehung für dieses Problem gibt?Java-Fehler: java.lang.IllegalArgumentException: Bereits von der VM verwendetes Signal: INT

Quelle:

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); 
    } 
} 

Ausgang:

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 

Weitere Informationen:

Ich fand heraus, etwas seltsam. Der Grund, warum es fehlschlägt, ist, weil ich das Programm in einem Shell-Skript als Hintergrundprozess ausführen.

dh sigtest.sh:

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

Wenn ich das Programm von der Befehlszeile ausführen, oder entfernen Sie die „&“ (dh es ist ein Vordergrundprozess innerhalb der Shell-Skript machen), ist es nicht habe ein Problem ... Ich verstehe nicht, warum das so ist.

+0

Jin, mit Ihrem Kommentar zu meiner Antwort, die JVM lässt Sie nicht einen Haken bei dieser Veranstaltung registrieren. Kannst du mehr darüber beschreiben, was du erreichen willst? Vielleicht gibt es einen Weg, dies zu tun, der mehr mit den Erwartungen der JVM übereinstimmt. – Yishai

+0

Ich möchte, dass das Programm ordnungsgemäß beendet wird, indem Sie einen "Bereinigungs" -Code aufrufen, wenn dieser unterbrochen wird. –

+0

Das Problem war JVM-spezifisch. Ich habe das Kopfgeld an Jitter vergeben, da seine Antwort "JVM implementation specific" beinhaltete und die meisten Tools zur Diagnose meines Problems zur Verfügung stellte. Danke an alle. –

Antwort

3

Dies ist möglicherweise ein JVM-Implementierungsspezifisches Problem. Wir verwenden eine undokumentierte/nicht unterstützte API (sun.misc.Signal/SignalHandler) und daher ist kein Vertrag über das Verhalten der API garantiert.

Die IBM JVM-Implementierung könnte Signalverarbeitungs-bezogene Dinge anders als die SUN JVM-Implementierung durchführen und somit dieses Problem verursachen. Dieser spezielle Anwendungsfall funktioniert also in der SUN JVM, nicht jedoch in der IBM JVM.

Aber versuchen Sie folgendes (ich kann es nicht ausprobieren mich):

alle Kombinationen Haben Sie den JVM beginnend mit einem/zwei/drei dieser Parameter und dort möglichen Wertekombinationen.

  1. die -Xrs Option angegeben/nicht
  2. Eigentum ibm.signalhandling.sigint Satz true/false
  3. Eigentum ibm.signalhandling.rs Satz angegeben true/false

(Die Eigenschaften, wo in mehreren über google gefunden Fehler Dumps, aber ich kann keine spezifische Dokumentation zu ihnen finden)

Ich weiß nicht, ob die IBM JVM auch diesen speziellen Flag unterstützt, aber man könnte versuchen, dies auch das Hinzufügen die in SUN JVM für einige Probleme mit Signal-Handler unter

-XX:-AllowUserSignalHandlers 

solaris linux/um genau zu sein scheint, oder versuchen, Verwenden Sie einen nativen Signal-Handler, wenn dies eine Option für Sie ist. Schauen Sie sich die Code-Beispiele zur Verfügung gestellt:

Obwohl es nicht auf Ihr spezielles Problem bezieht, ein IBM-Artikel auf JVM Signalverarbeitung (etwas veraltet, aber immer noch größtenteils korrekt). Bei Proben, für die native Code-Signal-Handler:

Revelations on Java signal handling and termination


Aber ich glaube, dass das alles ohne Erfolg, wie die IBM JVM Implementierung sein kann, könnte sich verlassen SIGINT selbst Handhabung korrekt funktionieren und so geben Sie nie Chance, sich selbst zu behandeln SIGINT.

Btw. von der description to the -Xrs flag Ich verstehe, dass es tatsächlich behindern Sie können, was Sie wollen. Es heißt

When -Xrs is used on Sun's JVM, the signal masks for SIGINT, SIGTERM, SIGHUP, and SIGQUIT are not changed by the JVM, and signal handlers for these signals are not installed.

Oder es könnte bedeuten, dass nur die JVM Standardaktionen für die Signale nicht ausgeführt werden. Oder es könnte von der JVM-Implementierung abhängen, was wirklich gemeint ist.

+0

Die Frage war JVM-spezifisch. Ich musste eine andere JVM installieren, um das gewünschte Verhalten zu erhalten. –

0

Die Ausnahme tritt auf, weil die VM bereits über einen Signalhandler für SIGINT verfügt. Was Sie dabei tun können/sollten, hängt vom Kontext ab, in dem diese Ausnahme ausgelöst wird.

0

Ich habe den gleichen Code ausprobiert und es funktioniert für mich. Ich denke also, es könnte einen Unterschied im Setup geben.

Nach der Zugabe von

System.out.println("Hello"); 

mit dem Griff Nachricht kann ich die Klasse so laufen:

[email protected]:/tmp/so$ java SignalTest & sleep 1s && kill -2 $! 
[1] 20467 
[email protected]:/tmp/so$ Hello 
[email protected]:/tmp/so$ 
[email protected]:/tmp/so$ java SignalTest 
[1]+ Done    java SignalTest 
+0

Ja, ich habe zwei Umgebungen. Eins ist 32 Bit Linux, es funktioniert gut mit Sun JVM. Eines ist 64-Bit-Linux, es funktioniert nicht auf diesem. –

+0

Mein Setup ist 64-Bit (2.6.24 ...) mit Sun JVM (HotSpot, 1.6.0_11). –

+0

Ich fange an zu fühlen, dass dies weniger ein Programmierproblem und mehr ein JVM-Problem ist. –

2

Versuchen Sie, die JVM mit einer -Xrs Option starten, die auf der IBM JVM nach gültig ist this sowieso. Das könnte den Konflikt verhindern.

EDIT: Als Reaktion auf die zugrunde liegenden Wunsch, schauen:

Runtime.getRuntime().addShutdownHook(Thread)

Sie ein Thread-Objekts Unterklasse, und es wird als Teil des shutdown (herausnehmen, dass -Xrs für diese Arbeit beginnen Gut). Einige Dinge (wie das Anhalten bei Runtime) können das verhindern, also müssen Sie sich der Möglichkeit bewusst sein, dass es einfach nicht passieren wird.

+0

, dass die Ausgabe ändert: java.lang.IllegalArgumentException auf die folgenden: java.lang.IllegalArgumentException

1

Wie von Heinz Kabutz geschrieben, hängen die Signale, die Sie fangen können, von dem Betriebssystem ab, auf dem Sie laufen, und wahrscheinlich von der JVM-Version. Wenn eine bestimmte OS/JVM-Kombination das Signal nicht registrieren lässt, haben Sie kein Glück. Vielleicht hilft das Optimieren mit den os/vm-Einstellungen.

Laut Ihrem Kommentar sollte ein Hinzufügen von shutdown hook, wie von Yishai vorgeschlagen, den Trick tun.

0

Ich habe dies mit einer anderen JVM-Implementierung (SuSE) anstelle von IBM zu arbeiten. Beim Umgang mit nicht dokumentierten Features scheint es, dass JVMs im Verhalten nicht sehr konsistent sind.

0

Ich habe auch das gleiche Problem. Ich führe das Java-Programm von einem ksh-Skript aus. Wenn ich das Skript mit dem Konto ausgeführt werden, die das csh Profil dh in/etc/passwd-Datei

userx hat: *: 7260: 20 ::/home/userx:/usr/bin/csh

Das Skript wird erfolgreich ausgeführt. Aber wenn ich es mit einem Konto ausführe, das ein anderes Profil als sh hat, gibt es den gleichen Fehler.

Also, die Lösung ist, Ihr Unix-Benutzerprofil in csh geändert zu bekommen.

0

Ich habe auch dieses Problem mit der IBM JVM (64 Bit) unter Linux festgestellt. Es stellte sich heraus, dass die JVM für die Signalmaske des Prozesses, der sie aufruft, empfindlich ist.

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

Beachten Sie, dass das Bit für SIGINT (Wert 2) in SigIgn gesetzt wird. Wenn Sie IBM JVM mit dieser Maske starten, wird die Installation eines Handlers für SIGINT verweigert. Ich arbeitete, um das Problem durch die JVM durch eine Python-Wrapper startet, der die SIGINT-Handler auf die Standardeinstellung zurücksetzt:

#!/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) 

Das erste Argument für den Wrapper der java Befehl ist, dann folgen die Argumente für die JVM.

Verwandte Themen