Come interrompere il processo java con grazia?

Come faccio a fermare un processo Java con grazia in Linux e Windows?

Quando Runtime.getRuntime().addShutdownHook si chiama, e quando non è vero?

Che cosa circa i finalizzatori, non aiutano qui?

Posso inviare qualche tipo di segnale ad un processo Java da una shell?

Sto cercando preferibilmente di soluzioni portatili.

  • dovresti definire cosa intendi con garbo. (per favore)
  • Presumo che significa che vogliono essere data la possibilità di “pulire” una delle risorse, il rilascio, serrature, e cancellare gli eventuali dati persistenti disco prima che il programma viene ucciso.
InformationsquelleAutor Ma99uS | 2008-10-10



7 Replies
  1. 78

    Arresto ganci eseguire in tutti i casi in cui la VM non è forzatamente ucciso. Quindi, se si dovesse emettere una “standard” uccidere (SIGTERM da un comando kill) quindi si eseguirà. Allo stesso modo, verranno eseguite dopo la chiamata System.exit(int).

    Tuttavia un hard kill (kill -9 o kill -SIGKILL) quindi non è eseguire. Allo stesso modo (e ovviamente) non eseguire se si tira l’alimentazione del computer, cadere in una vasca di lava bollente, o battere la CPU in pezzi con una mazza. Probabilmente già sapeva che, anche se.

    Finalizzatori davvero dovrebbe funzionare così, ma è meglio non fare affidamento su questo per l’arresto di pulitura, ma piuttosto fare affidamento sul vostro arresto ganci per fermare le cose in modo pulito. E, come sempre, di essere cauti con i deadlock (ho visto troppi arresto ganci per appendere l’intero processo)!

    • Purtroppo, questo non sembra funzionare su Windows 7 (64bit). Ho provato con taskill, senza la forza di bandiera, e verifica il seguente errore: “ERRORE: Il processo con PID 14324 potrebbe non essere terminato. Motivo: Questo processo può essere terminato con forza (con l’opzione /F).” Fornire la forza di opzione “/f”, ovviamente, si chiude il processo immediatamente.
    • Non si può fare affidamento su finalizzatori in fase di esecuzione.
  2. 47

    Ok, dopo tutte le possibilità che ho scelto di lavorare con “Java di Gestione e Monitoraggio”

    Panoramica è qui

    Che consente il controllo di un’applicazione da un altro in modo relativamente facile. È possibile chiamare l’applicazione di controllo da uno script per interrompere l’applicazione controllata con grazia prima di ucciderlo.

    Qui è il codice semplificato:

    Applicazione controllata:

    eseguito con le seguenti parametri VM:

    -Dcom.sole.di gestione.jmxremote

    -Dcom.sole.di gestione.jmxremote.port=9999

    -Dcom.sole.di gestione.jmxremote.autenticare=false

    -Dcom.sole.di gestione.jmxremote.ssl=false

    //ThreadMonitorMBean.java
    public interface ThreadMonitorMBean
    {
    String getName();
    void start();
    void stop();
    boolean isRunning();
    }
    
    //ThreadMonitor.java
    public class ThreadMonitor implements ThreadMonitorMBean
    {
    private Thread m_thrd = null;
    
    public ThreadMonitor(Thread thrd)
    {
        m_thrd = thrd;
    }
    
    @Override
    public String getName()
    {
        return "JMX Controlled App";
    }
    
    @Override
    public void start()
    {
        //TODO: start application here
        System.out.println("remote start called");
    }
    
    @Override
    public void stop()
    {
        //TODO: stop application here
        System.out.println("remote stop called");
    
        m_thrd.interrupt();
    }
    
    public boolean isRunning()
    {
        return Thread.currentThread().isAlive();
    }
    
    public static void main(String[] args)
    {
        try
        {
            System.out.println("JMX started");
    
            ThreadMonitorMBean monitor = new ThreadMonitor(Thread.currentThread());
    
            MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    
            ObjectName name = new ObjectName("com.example:type=ThreadMonitor");
    
            server.registerMBean(monitor, name);
    
            while(!Thread.interrupted())
            {
                //loop until interrupted
                System.out.println(".");
                try 
                {
                    Thread.sleep(1000);
                } 
                catch(InterruptedException ex) 
                {
                    Thread.currentThread().interrupt();
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            //TODO: some final clean up could be here also
            System.out.println("JMX stopped");
        }
    }
    }

    Applicazione di controllo:

    con l’ interrompere o inizio come argomento della riga di comando

    public class ThreadMonitorConsole
    {
    
    public static void main(String[] args)
    {
        try
        {   
            //connecting to JMX
            System.out.println("Connect to JMX service.");
            JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
            JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
            MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
    
            //Construct proxy for the the MBean object
            ObjectName mbeanName = new ObjectName("com.example:type=ThreadMonitor");
            ThreadMonitorMBean mbeanProxy = JMX.newMBeanProxy(mbsc, mbeanName, ThreadMonitorMBean.class, true);
    
            System.out.println("Connected to: "+mbeanProxy.getName()+", the app is "+(mbeanProxy.isRunning() ? "" : "not ")+"running");
    
            //parse command line arguments
            if(args[0].equalsIgnoreCase("start"))
            {
                System.out.println("Invoke \"start\" method");
                mbeanProxy.start();
            }
            else if(args[0].equalsIgnoreCase("stop"))
            {
                System.out.println("Invoke \"stop\" method");
                mbeanProxy.stop();
            }
    
            //clean up and exit
            jmxc.close();
            System.out.println("Done.");    
        }
        catch(Exception e)
        {
            //TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    }


    Che è. 🙂

  3. 7

    Un altro modo: l’applicazione può aprire un server socet e attendere informazioni arrivato ad esso. Per esempio una stringa con una “magia”, la parola 🙂 e quindi reagire di fare shutdown: Sistema.exit(). È possibile inviare tali informazioni al socke utilizzando un’applicazione esterna, come ad esempio telnet.

  4. 2

    Domanda Simile Qui

    Finalizzatori in Java sono male. Essi aggiungono un sacco di overhead per la raccolta dei rifiuti. Evitare, quando possibile.

    Il shutdownHook sarà soltanto quando la macchina virtuale è in fase di arresto. Penso che molto bene può fare quello che vuoi.

    • Così shutdownHook viene chiamato in TUTTI i casi? Che cosa se ‘uccidere’ il processo da shell?
    • Beh, non se si sta dando un kill -9 🙂
  5. 2

    Qui è un po ‘ complicato, ma una soluzione portatile:

    • Nell’applicazione di implementare un arresto gancio
    • Quando si desidera spegnere il JVM con grazia, installare un Agente Java che chiama Sistema.exit() utilizzando il Allegare API.

    Ho implementato l’Agente Java. È disponibile su Github: https://github.com/everit-org/javaagent-shutdown

    Descrizione dettagliata circa la soluzione è disponibile qui: https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process/

  6. 0

    Segnalazione in Linux può essere fatto con “kill” (uomo uccidere per i segnali disponibili), sarebbe necessario l’ID di processo per farlo. (ps ax | grep java) o qualcosa di simile, o memorizzare l’id del processo, quando il processo viene creato (questo viene usato in linux i file di avvio, vedere /etc/init.d)

    Portatile segnalazione può essere effettuata tramite l’integrazione di un SocketServer in applicazione java. Non è difficile e ti dà la libertà di inviare qualsiasi comando che si desidera.

    Se si intende, infine, le clausole in vece di finalizzatori; non extecuted quando il Sistema.exit() viene chiamato.
    Finalizzatori dovrebbe funzionare, ma non dovrebbe davvero fare qualcosa di più significativo, ma la stampa di un debug istruzione. Sono pericolosi.

Lascia un commento