89 votes

Comment arrêter gracieusement un processus java ?

Comment arrêter gracieusement un processus java sous Linux et Windows ?
Quand Runtime.getRuntime().addShutdownHook est-il appelé, et quand ne l'est-il pas ?
Et les finaliseurs, sont-ils utiles ici ?
Puis-je envoyer une sorte de signal au processus java depuis le shell ?

Je cherche une solution de préférence portable.
Merci,

83voto

jsight Points 16025

Les hooks d'arrêt s'exécutent dans tous les cas où la VM n'est pas tuée de force. Ainsi, si vous émettez un kill "standard" ( SIGTERM d'une commande kill) alors ils s'exécuteront. De même, ils s'exécuteront après avoir appelé System.exit(int) .

Cependant, une mise à mort difficile ( kill -9 ou kill -SIGKILL ), ils n'exécuteront pas. De même (et évidemment), ils ne s'exécuteront pas si vous coupez l'alimentation de l'ordinateur, si vous le jetez dans une cuve de lave bouillante ou si vous réduisez l'unité centrale en pièces avec une masse. Mais vous le saviez probablement déjà.

Les finaliseurs doivent également être exécutés, mais il est préférable de ne pas compter sur eux pour le nettoyage de l'arrêt, mais plutôt sur vos hooks d'arrêt pour arrêter les choses proprement. Et, comme toujours, faites attention aux deadlocks (j'ai vu beaucoup trop de crochets d'arrêt bloquer le processus entier) !

47voto

Ma99uS Points 2231

Ok, après toutes les possibilités, j'ai choisi de travailler avec "Java Monitoring and Management".
La vue d'ensemble est ici
Cela vous permet de contrôler une application depuis une autre de manière relativement simple. Vous pouvez appeler l'application de contrôle à partir d'un script pour arrêter l'application contrôlée avant de la tuer.

Voici le code simplifié :

Application contrôlée :
exécutez-le avec les paramètres VM suivants :
-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=9999
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.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");
    }
}
}

Contrôle de l'application :
l'exécuter avec le arrêter ou commencer comme argument de ligne de commande

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

C'est tout. :-)

7voto

Une autre façon : votre application peut ouvrir un socet de serveur et attendre une information qui lui parvient. Par exemple une chaîne de caractères avec un mot "magique" :) et ensuite réagir pour faire un arrêt : System.exit(). Vous pouvez envoyer une telle information au socke en utilisant une application externe comme telnet.

2voto

Steve g Points 1955

Question similaire Ici

Les Finalizers en Java sont mauvais. Ils ajoutent beaucoup de surcharge à la collecte des déchets. Évitez-les autant que possible.

Le shutdownHook ne sera appelé que lorsque la VM s'arrêtera. Je pense que cela peut très bien faire ce que vous voulez.

1voto

PintSizedCat Points 4221

Dans le cas de shutdown Hook, avez-vous lu la javadoc correspondante ?

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X