9.15 Einen Abbruch der virtuellen Maschine erkennen
Läuft ein Java-Programm in der virtuellen Maschine, so kann der Benutzer zu jeder Zeit das Programm dadurch beenden, dass er die virtuelle Maschine beendet. Dies kann aber für das Programm sehr unsicher sein, und zwar aus den gleichen Gründen wie bei einem unvermittelten Abbruch durch die stop()-Methode der Klasse Thread.
Ein Unix-System erzeugt Signale, die das Programm informieren, dass es beendet werden soll. Dies geschieht zum Beispiel, wenn der Benutzer das Programm mit der Tastenkombination (Strg)+(C) abbricht, das System herunterfährt oder der Benutzer sich vom System abmeldet. Ein Abbruchsignal ist beispielsweise SIGINT. Jedes Programm unter Unix kann diese Signale abfangen und darauf reagieren. Auf diese Weise lassen sich auch Programme schreiben, die dieses Abbruchsignal einfach ignorieren. Ein sauberes Programm kommt der Aufforderung nach, gibt Ressourcen frei und beendet sich.
Um das Ende der virtuellen Maschine zu erkennen, ist in den Versionen bis Java 1.3 viel komplizierter nativer Quellcode entstanden, der die Signale erkennt und an das Java-Programm weiterleitet. Unter Unix lässt sich die Bibliothek JavaSignals von Kevin Hester unter http://interstice.com/~kevinh/projects/javasignals/index.html verwenden, die Signale erkennt und abblockt. Seit der JDK 1.3-Version bietet die Runtime-Klasse eine Methode an, mit der sich ein Thread bei einem Abbruchwunsch informieren lassen kann.
Mit folgender Zeile starten wir den Thread t, wenn die JVM beendet wird und das Signal abgefangen werden kann. Die Formulierung ist extra vorsichtig, da unter Windows in einer Konsole zwar ähnlich wie unter Unix bei der Eingabe von (Strg)+(C) das Ende erkannt werden kann, jedoch nicht, wenn mit dem Task-Manager der Prozess beendet wird. Unter Windows ist dies ein Aufruf von TerminateProcess. Unter Unix entspricht dem ein SIGKILL-Signal.
Thread t = ...
Runtime.getRuntime().addShutdownHook( t );
Zusätzlich zum Abbruch wird der Thread auch immer dann gestartet, wenn das Programm normal beendet wird. Das Teilwort Hook erinnert an einen Haken, der sich ins System einhängt, um Informationen abzugreifen. Der Hook ist ein initialisierter, aber noch nicht gestarteter Thread. Es können durchaus mehrere Threads unter dem Shutdown-Hook installiert sein. Wenn sich dann die JVM beendet, werden die Threads in beliebiger Reihenfolge abgearbeitet.
Beispiel Eine Endlosschleife schmort im eigenen Saft. Der eingefügte Hook reagiert auf das Ende der virtuellen Maschine. Das Programm muss auf der Konsole beendet werden, da die meisten Entwicklungsumgebungen das (Strg)+(C) nicht an die Java-Umgebung weiterleiten.
|
Listing 9.19 ThatsMyEnd.java
class ThatsMyEnd
{
public static void main( String args[] )
{
Runtime run = Runtime.getRuntime();
run.addShutdownHook( new Thread()
{
public void run()
{
System.out.println( "Hilfe! Man will mir an die Wäsche" );
}
} );
while ( true )
;
}
}
|
void addShutdownHook( Thread hook )
Startet den angegebenen Thread, wenn die JVM beendet wird. Der Thread kann keinen neuen Thread unter dem Hook registrieren. Die run()-Methode des Threads sollte schnell ablaufen, um das Beenden der JVM nicht länger als nötig aufzuhalten. Es ist nicht möglich (vorgesehen), das bevorstehende Ende der JVM zu verhindern. |
|
boolean removeShutdownHook( Thread hook )
Entfernt den angegebenen Hook. Rückgabewert ist true, falls der Hook registriert war und entfernt werden konnte. |
|