When it comes to developing applications, we as software developers always (almost always at least!) stive to make our code as robust and clean as possible. By robust I mean error conditions are handled gracefully and clean meaning that whatever resources we have opened up are closed appropriately. But let’s face it, there will be times when mistakes are made or the unexpected happens. Fortunately, Java provides some great tools that allow for handling just such situations – shutdown hooks and uncaught exception handlers.
Shutdown Hooks
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { doSomeCleanup(); } }));
Now when a program exits, the code specified in your shutdown hook will run, giving you one last chance to ensure things are left in a consistent state. There are some caveats with shutdown hooks:
- Don’t assume other services will be available, code defensively
- Make every attempt to make sure the code executes quickly
- Make sure the code is written to avoid deadlocks
Ideally, shutdown hooks are to ensure that resources are cleaned up properly and not a replacement for good coding practices.
Uncaught Exception Handlers
The Thread.UncaughtExceptionHandler represents a chance to do what the name of the interface implies, handle any uncaught exceptions. As with the shutdown hook, the UncaughtExceptionHandler should not be used as an excuse to get away from good coding practices. Rather, the uncaught exception handler is the last line of defense against the truly unexpected exceptions. Setting an UncaughtExceptionHander is equally as easy:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread thread, Throwable throwable) { handleTheUnexpectedError(); } });
Now with just four lines of code, you have given your program the ability to handle unexpected errors gracefully.
I hope the reader found these tips useful and have a great Christmas!
Meta: this post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on! Want to write for the blog? We are looking for contributors to fill all 24 slot and would love to have your contribution! Contact Attila Balazs to contribute!
Attila-Mihaly Balazs December 17, 2012
An idea which should be clear from the code (since it says "new Thread") but probably worth emphasizing: each shutdown hook is a separate thread and they run concurrently. So all the usual considerations of multi-threaded applications apply (don't change unsynchronized data, ensure the order of synchronization, etc).
Also, shutdown hooks may not be executed (if the process is kill'd for example), thus we shouldn't rely on them to execute operations which are critical for the program (the kind "we must do this or next time the program won't start").
Alexander Turner December 17, 2012
Attila, I was once team lead on a project with exactly this issue. We used shut down hooks to release licenses to native code which was loaded via JNI. All kinds of threading issues turned up as the thread doing the shutdown is not the thread which ran the native lib. Also, if the process crashed (as stuff with JNI in does from time to time) the licenses were not released. However, we did get it to work.
Take home message, for high grade software, expect to put in a bit of extra work if you are using shutdown hooks.
Attila-Mihaly Balazs December 17, 2012
I would also add:
– read up on signal handling if you're writing JNI: http://nerds-central.blogspot.ro/2011/04/java-jvm-jni-and-signal-handling.html 🙂
– prefer software which doesn't have such licensing code (*cough* FLOSS *cough*) 🙂