Oft benötigt man in komplexen Java Anwendungen auch eine Datenbankverbindung, in großen Projekten greift man hier eigentlich immer auf ein Persistenz-Framework zurück, Beispiele hierfür sind Hibernate und PriDE. Beim Beenden einer Applikation sollte die Datenbankverbindung nun idealerweise geschlossen werden. Doch oft vergisst man dies oder geht davon aus, dass das die JVM schon für einen erledigt. Oder was passiert wenn man die Anwendung abbricht und gar keine definierte „Beenden“ Methode durchlaufen wird?
Hierfür gibt es seit Java 1.3 die sogenannten Shutdown Hooks. Das sind Methoden die man via Java an die JVM anhängen kann, diese Methoden werden dann kurz vor dem Beenden der JVM aufgerufen, automatisch. Dieses Konzept ist ähnlich der finalize() Methoden, jedoch eben global für eine JVM.
Die Vorteile liegen hier jedoch klar auf der Hand:
- lediglich eine Registrierung der Hooks
- Entwickler müssen sich nicht um die DB Verbindung kümmern
- sicheres Schließen aller offenen Verbindungen etc.
- weitere Aufräumarbeiten möglich…
So kann man natürlich nicht nur eine Datenbankverbindung damit beenden, sondern auch Temp-Ordner löschen oder Loggings durchführen.
Die Registrierung eines solchen Hooks ist sehr einfach:
// set up service termination hook (gets called // when the JVM terminates from a signal): MyShutdownHook sh = new MyShutdownHook(this); Runtime.getRuntime().addShutdownHook(sh); |
Und der dazugehörige Shutdown Hook:
/** * Shutdown hook class */ class MyShutdownHook extends Thread { private CallingClass managedClass; public MyShutdownHook(CallingClass managedClass) { super(); this.managedClass = managedClass; } public void run() { System.out.println("Hook MyShutdownHook thread started"); try { managedClass.freeResources(); } catch (Exception e) { e.printStackTrace(); } } } |
In diesem konkreten Fall wird dem Hook die Klasse übergeben, die diesen registriert. Logischerweise besitzt diese dann eine Methode freeResources(); welche die DB Verbindung kappt, oder eben Ähnliches tut. Natürlich muss man dort nichts übergeben, das bleibt einem selber überlassen, wichtig ist nur die Registrierung via Runtime.getRuntime().addShutdownHook(sh);.
Der Hook selber muss von Thread abgeleitet sein oder das Runnable Interface implementieren, kann wie man selber mag. Der Hook läuft am Ende in einem eigenen Thread, werden mehrere Hooks registriert laufen diese parallel. Außerdem sollte man darauf achten die Hooks kurz und schnell zu halten, denn schließlich blocken sie die JVM obwohl ein System*.exit(0); oder Ähnliches abgesetzt wurde. Daher sollte man hier keine großen Aktionen mehr starten sondern schnell und sauber arbeiten.
Ein komplettes Beispiel kann hier heruntergeladen werden.
Hinweis:
Arbeitet man mit Eclipse, so wird der Hook nicht gestartet, wenn die JVM über den Terminate-Button (das rote Rechteck) beendet wird. Den dieser Button killt die JVM wirklich sofort und zwar den ganzen Prozess direkt, daher hat die JVM keine Chance noch einen Hook auszuführen, den das Ende bekommt sie quasi gar nicht mit, dann ist sie schon tot ;).
Coole Sache, kannt ich bisher nicht
Jap, habe ich auch gedacht als ich das gefunden habe :)