2009-06-26 11 views
5

Sto analizzando un problema Java (utilizzando IBM JVM 1.4.2 64-bit) su Red Hat Linux. Mi chiedo se qualcuno ha già visto questo messaggio di errore e sa se c'è una soluzione a questo problema?Errore Java: java.lang.IllegalArgumentException: Segnale già utilizzato dalla VM: INT

Fonte:

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

uscita:

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 

Informazioni aggiuntive:

ho scoperto qualcosa di strano. Il motivo per cui non funziona è perché sto eseguendo il programma all'interno di uno script di shell come processo in background.

cioè sigtest.sh:

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

Se eseguo il programma da linea di comando, o rimuovere il "&" (cioè renderlo un processo in primo piano all'interno dello script di shell), non è così avere un problema ... Non capisco perché sia ​​così.

+0

Jin, dato il tuo commento sulla mia risposta, la JVM non ti permette di registrarti su questo evento. Puoi descrivere di più su cosa stai cercando di realizzare? Forse c'è un modo per farlo che è più in sintonia con le aspettative della JVM. – Yishai

+0

Voglio che il programma esca con grazia eseguendo un po 'di codice "clean up" se è stato interrotto. –

+0

Il problema era specifico JVM. Ho assegnato il premio a Jitter, poiché la sua risposta includeva "implementazione specifica JVM" e forniva il maggior numero di strumenti per diagnosticare il mio problema. Grazie a tutti. –

risposta

3

Questo potrebbe essere un problema specifico di implementazione JVM. Stiamo utilizzando un'API non documentata/non supportata (sun.misc.Signal/SignalHandler) e pertanto non è garantito alcun contratto sul comportamento dell'API.

L'implementazione IBM JVM potrebbe fare cose correlate alla gestione dei segnali in modo diverso dall'implementazione SUN JVM e quindi causare questo problema. In modo che questo caso d'uso specifico funzioni in SUN JVM ma non in IBM JVM.

Ma provare quanto segue (non riesco a provare io stesso):

fare tutte le combinazioni al largo di iniziare la JVM con uno/due/tre di questi parametri e là le possibili combinazioni di valori.

  1. l'opzione -Xrs specificato/Non specificato
  2. la proprietà ibm.signalhandling.sigint insieme a true/false
  3. la proprietà ibm.signalhandling.rs insieme a true/false

(Le proprietà dove trovati tramite Google in diversi errori, ma non riesco a trovare alcuna documentazione specifica su di essi)

Non so se l'IBM JVM supporta anche questo flag speciale, ma si potrebbe provare ad aggiungere anche questo che a SUN JVM sembra essere specifico per alcuni problemi con i gestori dei segnali sotto Linux/Solaris

-XX:-AllowUserSignalHandlers 

o provare usando un gestore di segnale nativo se questa è un'opzione per te. Controllate il codice campioni forniti:

Anche se non si riferiscono al tuo problema specifico, un articolo su IBM JVM gestione del segnale (leggermente datato ma ancora in gran parte corretto). Con i campioni per i gestori di segnale codice nativo:

Revelations on Java signal handling and termination


ma credo che questo può essere tutti senza alcun risultato come l'implementazione di IBM JVM poteva contare sulla gestione SIGINT stesso per funzionare correttamente e quindi mai dando una possibilità di gestire autonomamente lo SIGINT.

Btw. dal description to the -Xrs flag capisco che in realtà potrebbe impedirti di fare ciò che desideri. Dice

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.

Oppure potrebbe significare che solo le azioni predefinite JVM per i segnali non vengono eseguite. Oppure potrebbe dipendere dall'implementazione della JVM cosa si intende realmente.

+0

La questione è stata JVM specifica. Ho dovuto installare un'altra JVM per ottenere il comportamento che desideravo. –

0

L'eccezione si verifica perché la macchina virtuale ha già un gestore di segnale installato per SIGINT. Ciò che puoi/dovrebbe fare in merito dipende dal contesto in cui viene generata questa eccezione.

0

Ho provato lo stesso codice e funziona per me. Quindi immagino ci possa essere qualche differenza nel setup.

Dopo aver aggiunto

System.out.println("Hello"); 

al messaggio maniglia posso correre la classe così:

[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

Sì, ho due ambienti. Uno è Linux a 32 bit, funziona perfettamente con Sun JVM. Uno è Linux a 64 bit, non funziona su questo. –

+0

La mia configurazione è 64-bit (2.6.24 ...) usando Sun JVM (HotSpot, 1.6.0_11). –

+0

Sto iniziando a sentire che questo è meno un problema di programmazione e più un problema JVM. –

2

provare ad accendere il JVM con un'opzione -Xrs che è valido su IBM JVM in base alle this comunque. Questo potrebbe prevenire il conflitto.

EDIT: In risposta al vostro desiderio di fondo, guarda:

Runtime.getRuntime().addShutdownHook(Thread)

È sottoclasse di un oggetto thread, e inizierà come parte della chiusura (togliere che -Xrs per questo al lavoro bene). Alcune cose (come chiamare halt on Runtime) possono impedire che ciò accada, quindi è necessario essere consapevoli della possibilità che semplicemente non finirà per accadere.

+0

che cambia l'output: java.lang.IllegalArgumentException al seguente: java.lang.IllegalArgumentException

1

Come scritto da Heinz Kabutz, i segnali che si possono intercettare dipendono dal sistema operativo su cui si sta eseguendo e in modo appropriato dalla versione JVM. Se una determinata combinazione os/jvm non ti consente di registrare il tuo segnale, allora sei sfortunato. Forse il tweaking con le impostazioni os/vm potrebbe aiutare.

Secondo il tuo commento, aggiungere un shutdown hook come proposto da Yishai dovrebbe fare il trucco.

0

Ho ottenuto che questo funzioni utilizzando un'implementazione JVM diversa (SuSE) anziché IBM. Quando si tratta di funzionalità non documentate, sembra che le JVM non siano molto coerenti nel comportamento.

0

Anch'io ho lo stesso problema. Eseguo il programma java da uno script ksh. Se faccio funzionare lo scritto con l'account che ha il profilo csh cioè, in/etc/passwd

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

Lo script verrà eseguito correttamente. Ma se lo eseguo con un account che ha un profilo diverso da sh, sta dando lo stesso errore.

Quindi, la soluzione è ottenere il proprio profilo utente unix modificato in csh.

0

Ho anche riscontrato questo problema con IBM JVM (64 bit) su Linux. Si è scoperto che la JVM è sensibile alla maschera di segnale del processo che la chiama.

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

Si noti che il bit per SIGINT (valore 2) è impostato in SigIgn. Quando si avvia IBM JVM con questa maschera, si rifiuta di installare un gestore per SIGINT. Ho lavorato tutto il problema lanciando JVM tramite un wrapper Python che reimposta il gestore SIGINT al default:

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

Il primo argomento l'involucro è il comando java, quindi seguire le argomentazioni per la JVM.

Problemi correlati