Hinzufügen von Shutdown Hooks für JVM-Anwendungen

1. Übersicht

Es ist normalerweise einfach, einen Dienst zu starten. Manchmal brauchen wir jedoch einen Plan, um einen ordnungsgemäß abzuschalten.

In diesem Tutorial werden wir uns verschiedene Möglichkeiten ansehen, wie eine JVM-Anwendung beendet werden kann. Anschließend verwenden wir Java-APIs, um JVM-Shutdown-Hooks zu verwalten. Weitere Informationen zum Herunterfahren der JVM in Java-Anwendungen finden Sie in diesem Artikel.

2. JVM herunterfahren

Die JVM kann auf zwei verschiedene Arten heruntergefahren werden:

  1. Ein kontrollierter Prozess
  2. Eine abrupte Art und Weise

Ein kontrollierter Prozess fährt die JVM herunter, wenn:

  • Der letzte Nicht-Daemon-Thread wird beendet. Wenn beispielsweise der Hauptthread beendet wird, startet die JVM den Herunterfahrvorgang
  • Senden eines Interrupt-Signals vom Betriebssystem. Zum Beispiel durch Drücken von Strg + C oder Abmelden vom Betriebssystem
  • Aufruf von System.exit () aus Java-Code

Während wir alle nach einem ordnungsgemäßen Herunterfahren streben, wird die JVM manchmal abrupt und unerwartet heruntergefahren. Die JVM wird abrupt heruntergefahren, wenn :

  • Senden eines Kill-Signals vom Betriebssystem. Zum Beispiel durch Ausgabe eines Kill -9
  • Aufruf von Runtime.getRuntime (). Halt () aus Java-Code
  • Das Host-Betriebssystem stirbt unerwartet ab, z. B. bei einem Stromausfall oder einer Betriebssystempanik

3. Haken herunterfahren

Mit der JVM können Registrierungsfunktionen ausgeführt werden, bevor das Herunterfahren abgeschlossen ist. Diese Funktionen sind normalerweise ein guter Ort, um Ressourcen oder ähnliche Haushaltsaufgaben freizugeben. In der JVM-Terminologie werden diese Funktionen als Hutdown-Hooks bezeichnet .

Shutdown-Hooks sind grundsätzlich initialisierte, aber nicht gestartete Threads . Wenn die JVM mit dem Herunterfahren beginnt, werden alle registrierten Hooks in einer nicht angegebenen Reihenfolge gestartet. Nachdem alle Hooks ausgeführt wurden, wird die JVM angehalten.

3.1. Hooks hinzufügen

Um einen Shutdown-Hook hinzuzufügen, können wir die Methode Runtime.getRuntime (). AddShutdownHook () verwenden:

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

Hier drucken wir einfach etwas in die Standardausgabe, bevor sich JVM selbst herunterfährt. Wenn wir die JVM wie folgt herunterfahren:

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

Dann werden wir sehen, dass der Hook die Nachricht tatsächlich in die Standardausgabe druckt.

Die JVM ist für das Starten von Hook-Threads verantwortlich . Wenn der angegebene Hook bereits gestartet wurde, löst Java daher eine Ausnahme aus:

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"); 

Natürlich können wir einen Hook auch nicht mehrmals registrieren:

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

3.2. Haken entfernen

Java bietet eine Doppelentfernungsmethode , um einen bestimmten Shutdown-Hook nach der Registrierung zu entfernen:

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

Die Methode removeShutdownHook () gibt true zurück , wenn der Shutdown-Hook erfolgreich entfernt wurde.

3.3. Vorsichtsmaßnahmen

Die JVM führt Shutdown-Hooks nur bei normalen Abbrüchen aus. Wenn also eine externe Kraft den JVM-Prozess abrupt beendet, hat die JVM keine Chance, Shutdown-Hooks auszuführen. Das Anhalten der JVM über Java-Code hat außerdem den gleichen Effekt:

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

Die Stopp- Methode beendet die aktuell ausgeführte JVM zwangsweise. Registrierte Shutdown-Hooks können daher nicht ausgeführt werden.

4. Fazit

In diesem Tutorial haben wir verschiedene Möglichkeiten untersucht, wie eine JVM-Anwendung möglicherweise beendet werden kann. Anschließend haben wir einige Laufzeit-APIs verwendet, um Shutdown-Hooks zu registrieren und die Registrierung aufzuheben.

Wie üblich ist der Beispielcode auf GitHub verfügbar.