Ajout de hooks d'arrêt pour les applications JVM

1. Vue d'ensemble

Il est généralement facile de démarrer un service. Cependant, nous devons parfois avoir un plan pour en arrêter un en douceur.

Dans ce didacticiel, nous allons examiner différentes manières dont une application JVM peut se terminer. Ensuite, nous utiliserons les API Java pour gérer les hooks d'arrêt JVM. Veuillez consulter cet article pour en savoir plus sur l'arrêt de la JVM dans les applications Java.

2. Arrêt de la JVM

La JVM peut être arrêtée de deux manières différentes:

  1. Un processus maîtrisé
  2. Une manière brusque

Un processus contrôlé arrête la JVM lorsque:

  • Le dernier thread non démon se termine. Par exemple, lorsque le thread principal se termine, la machine virtuelle Java démarre son processus d'arrêt
  • Envoi d'un signal d'interruption depuis le système d'exploitation. Par exemple, en appuyant sur Ctrl + C ou en vous déconnectant du système d'exploitation
  • Appel de System.exit () à partir du code Java

Alors que nous nous efforçons tous d'arrêter en douceur, la JVM peut parfois s'arrêter de manière brusque et inattendue. La JVM s'arrête brusquement lorsque :

  • Envoi d'un signal d'arrêt depuis le système d'exploitation. Par exemple, en émettant un kill -9
  • Appel de Runtime.getRuntime (). Halt () à partir du code Java
  • Le système d'exploitation hôte meurt de manière inattendue, par exemple en cas de panne de courant ou de panique du système d'exploitation

3. Crochets d'arrêt

La machine virtuelle Java autorise l'exécution des fonctions d'enregistrement avant la fin de son arrêt. Ces fonctions sont généralement un bon endroit pour libérer des ressources ou d'autres tâches ménagères similaires. Dans la terminologie JVM, ces fonctions sont appelées s hutdown hooks .

Les hooks d'arrêt sont essentiellement des threads initialisés mais non démarrés . Lorsque la machine virtuelle Java commence son processus d'arrêt, elle démarre tous les hooks enregistrés dans un ordre non spécifié. Après avoir exécuté tous les hooks, la JVM s'arrêtera.

3.1. Ajout de crochets

Afin d'ajouter un hook d'arrêt, nous pouvons utiliser la méthode Runtime.getRuntime (). AddShutdownHook () :

Thread printingHook = new Thread(() -> System.out.println("In the middle of a shutdown")); Runtime.getRuntime().addShutdownHook(printingHook);

Ici, nous imprimons simplement quelque chose sur la sortie standard avant que JVM ne s'arrête. Si nous arrêtons la JVM comme suit:

> System.exit(129); In the middle of a shutdown

Ensuite, nous verrons que le hook imprime réellement le message sur la sortie standard.

La JVM est responsable du démarrage des threads de hook . Par conséquent, si le hook donné a déjà été démarré, Java lèvera une exception:

Thread longRunningHook = new Thread(() -> { try { Thread.sleep(300); } catch (InterruptedException ignored) {} }); longRunningHook.start(); assertThatThrownBy(() -> Runtime.getRuntime().addShutdownHook(longRunningHook)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Hook already running"); 

De toute évidence, nous ne pouvons pas non plus enregistrer un hook plusieurs fois:

Thread unfortunateHook = new Thread(() -> {}); Runtime.getRuntime().addShutdownHook(unfortunateHook); assertThatThrownBy(() -> Runtime.getRuntime().addShutdownHook(unfortunateHook)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Hook previously registered");

3.2. Suppression des crochets

Java fournit une méthode de suppression double pour supprimer un hook d'arrêt particulier après son enregistrement:

Thread willNotRun = new Thread(() -> System.out.println("Won't run!")); Runtime.getRuntime().addShutdownHook(willNotRun); assertThat(Runtime.getRuntime().removeShutdownHook(willNotRun)).isTrue(); 

La méthode removeShutdownHook () renvoie true lorsque le hook d'arrêt est correctement supprimé.

3.3. Mises en garde

La JVM exécute les hooks d'arrêt uniquement en cas de terminaisons normales. Ainsi, lorsqu'une force externe tue brusquement le processus JVM, la JVM n'aura pas la possibilité d'exécuter des hooks d'arrêt. De plus, l'arrêt de la JVM à partir du code Java aura également le même effet:

Thread haltedHook = new Thread(() -> System.out.println("Halted abruptly")); Runtime.getRuntime().addShutdownHook(haltedHook); Runtime.getRuntime().halt(129); 

La méthode halt met fin de force à la JVM en cours d'exécution. Par conséquent, les hooks d'arrêt enregistrés n'auront pas la possibilité de s'exécuter.

4. Conclusion

Dans ce didacticiel, nous avons examiné différentes manières dont une application JVM peut éventuellement se terminer. Ensuite, nous avons utilisé quelques API d'exécution pour enregistrer et désenregistrer les hooks d'arrêt.

Comme d'habitude, l'exemple de code est disponible over sur GitHub.