web-dev-qa-db-fra.com

Capturez SIGINT dans Java

Quelle est la meilleure façon de capturer un signal d'arrêt en Java sans utiliser JNI. J'ai découvert le Sun.misc.Signal et le Sun.misc.SignalHandler et l'avertissement de la possibilité d'être supprimé dans les prochaines versions.

L'utilisation de JNI pour appeler une bibliothèque c serait-elle la seule option que j'ai?

39
Begui

La manière de gérer cela serait d'enregistrer un hook shutdown . Si vous utilisez ( [~ # ~] sigint [~ # ~] ) kill -2 provoquera la fermeture du programme et l'exécution des hooks d'arrêt.

Enregistre un nouveau hook d'arrêt de machine virtuelle.

La machine virtuelle Java s'arrête en réponse à deux types d'événements:

  • Le programme se ferme normalement, lorsque le dernier thread non démon se termine ou lorsque la méthode exit (de manière équivalente, System.exit) est invoquée, ou

  • La machine virtuelle est arrêtée en réponse à une interruption utilisateur, telle que la saisie de ^ C, ou un événement à l'échelle du système, tel que la fermeture de session utilisateur ou l'arrêt du système.

J'ai essayé le programme de test suivant sur OSX 10.6.3 et sur kill -9 il a [~ # ~] pas [~ # ~] exécuté le hook d'arrêt, ne pensait pas que ce serait le cas. Sur un kill -15 it [~ # ~] [~ # ~] exécute le hook d'arrêt à chaque fois.

public class TestShutdownHook
{
    public static void main(final String[] args) throws InterruptedException
    {
        Runtime.getRuntime().addShutdownHook(new Thread()
        {
            @Override
            public void run()
            {
                System.out.println("Shutdown hook ran!");
            }
        });

        while (true)
        {
            Thread.sleep(1000);
        }
    }
}

C'est la manière documentée d'écrire vos propres gestionnaires de signaux qui ne sont pas des hooks d'arrêt en Java. Soyez averti que le com.Sun.misc packages et ne sont pas pris en charge et peuvent être modifiés ou disparaître à tout moment et n'existent probablement que dans la JVM Sun.

58
user177800

Depuis au moins Java 6, la commande HotSpot Java a eu un -Xrs flag pour désactiver les gestionnaires de signaux JVM.

Si vous l'utilisez, vous devez implémenter vos propres gestionnaires SIGINT, SIGTERM, SIGHUP et SIGQUIT, dont un pour appeler explicitement System.exit().

Remarque: cela signifie que la fonction de vidage de thread de SIGQUIT est désactivée lorsque le -Xrs le drapeau est présent.

Voir https://docs.Oracle.com/javase/8/docs/technotes/tools/unix/Java.html#BABHDABI (également disponible sur les contreparties Windows et Solaris Java ).

5
delitescere

Jetez un œil à Integrating Signal and Exception Handling décrivant la capacité de la JVM HotSpot à enchaîner les signaux. Cela implique cependant une supercherie de niveau C.

Java.lang.Runtime.addShutdownHook(Thread) ne suffirait-il pas à votre objectif? Ces hooks sont exécutés par la JVM à la fin, y compris la réception de SIGINT, tant que la JVM est capable de les exécuter.

4
Asgeir S. Nilsen