Comment arrêter le processus java avec élégance?

Comment puis-je arrêter un processus Java avec élégance sous Linux et Windows?

Quand Runtime.getRuntime().addShutdownHook , et quand est-il pas?

Qu'en est-il des finaliseurs, aident-ils ici?

puis-je envoyer une sorte de signal à un processus Java à partir d'un shell?

je cherche de préférence des solutions portables.

84
demandé sur Lii 2008-10-10 17:17:36

7 réponses

Les crochets D'arrêt

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

Toutefois, un dur à tuer ( kill -9 ou kill -SIGKILL ) alors qu'ils ne sera pas exécuté. De même (et évidemment) ils ne s'exécuteront pas si vous tirez la puissance de l'ordinateur, le déposez dans une cuve de lave bouillante, ou battre le CPU dans morceaux avec un marteau de forgeron. Mais tu le savais probablement déjà.

finaliseurs devraient vraiment fonctionner aussi bien, mais il est préférable de ne pas compter sur cela pour le nettoyage d'arrêt, mais plutôt compter sur vos crochets d'arrêt pour arrêter les choses proprement. Et, comme toujours, soyez prudent avec les blocages (j'ai vu beaucoup trop de crochets d'arrêt accrocher le processus entier)!

74
répondu jsight 2014-11-04 15:31:37

Ok, après toutes les possibilités que j'ai choisi de travailler avec "Java Monitoring and Management"

aperçu est ici

Cela vous permet de contrôler une application d'une autre d'une manière relativement facile. Vous pouvez appeler l'application de contrôle à partir d'un script pour arrêter l'application contrôlée gracieusement avant de le tuer.

voici le code simplifié:

application contrôlée:

exécutez-le avec les paramètres VM suivants:

- Dcom.soleil.gestion.jmxremote

- Dcom.soleil.gestion.jmxremote.port=9999

- Dcom.soleil.gestion.jmxremote.authentifier=false

- Dcom.soleil.gestion.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");
    }
}
}

commande application:

lancez-le avec le stop ou start 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. :-)

47
répondu Ma99uS 2008-10-16 14:36:01

Une autre façon: votre application peut ouvrir un serveur socet et d'attendre une information est arrivée. Par exemple une chaîne avec un mot "magique":) et puis réagir pour faire shutdown: System.sortie.)( Vous pouvez envoyer ces informations au socke en utilisant une application externe comme telnet.

7
répondu 2009-06-17 15:19:03

Question Similaire Ici

les finaliseurs en Java sont mauvais. Ils ajoutent beaucoup de frais généraux à la collecte des ordures. Éviter autant que possible.

le shutdownHook ne sera appelé que lorsque la VM s'éteint. Je pense qu'il pourrait très bien faire ce que vous voulez.

2
répondu Steve g 2017-05-23 12:10:35

Voici une solution un peu délicate, mais portable:

  • dans votre application mettre en œuvre un crochet d'arrêt
  • quand vous voulez fermer votre JVM avec élégance, installez un Agent Java qui appelle le système .exit() à l'aide de la Joindre API .

j'ai implémenté L'Agent Java. Il est disponible sur Github: https://github.com/everit-org/javaagent-shutdown

une description détaillée de la solution est disponible ici: https://everitorg.wordpress.com/2016/06/15/shutting-down-a-jvm-process /

2
répondu Balazs Zsoldos 2016-06-16 08:33:10

signalisation dans Linux peut être fait avec "kill" (homme tuer pour les signaux disponibles), vous auriez besoin de l'ID de processus pour le faire. (ps ax / grep java) ou quelque chose comme ça, ou stocker l'id du processus lorsque le processus est créé (ceci est utilisé dans la plupart des fichiers de démarrage linux, voir /etc/init.d)

signalisation Portable peut être fait en intégrant un SocketServer dans votre application java. Ce n'est pas si difficile et vous donne la liberté d'envoyer n'importe quel commandement que vous voulez.

si vous voulez dire finalement des clauses au lieu de finalisateurs; ils ne sont pas extecuted quand le système.exit() est appelée. Les finaliseurs devraient fonctionner, mais ne devraient pas vraiment faire quoi que ce soit de plus significatif mais imprimer une instruction de débogage. Ils sont dangereux.

0
répondu extraneon 2008-10-10 14:37:42

Merci pour les réponses. Les crochets d'arrêt Se Couchent comme quelque chose qui fonctionnerait dans mon cas. Mais je suis aussi tombé sur le truc appelé surveillance et gestion des haricots:

http://java.sun.com/j2se/1.5.0/docs/guide/management/overview.html

Qui donne de belles possibilités, pour la surveillance à distance, et la manipulation du processus java. (Introduit en Java 5)

0
répondu Ma99uS 2008-10-10 17:11:23