I have an application with a well defined Try/Catch/Finally chain that exits and executes the finally block just fine under normal conditions, however when someone prematurely hits the red X in the GUI, the program fully exists (code = 0) and the main thread's finally block isn't called.
In fact, I do want the program to exit upon a click of the red-X, but what I do not want is a skipping of the finally{} block! I sort of put in the most important part of the finally block manually in the GUI but I really do not want to do it this way since I want the GUI decoupled from the actual program:
class GUI { // ...
...
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
try {
processObject.getIndicatorFileStream().close();
} catch (Exception ignore) {}
System.exit(0);
}
});
...
}
But I'd prefer to just have a call like this:
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
And make sure that all the finally{} blocks get called from each thread after the Exit.
I know this is actually expected. If the application is closed from a separate thread (say the GUI thread) then the main thread will just stop in its tracks.
In short -- how do I ensure that a System.exit(0) or a JFrame.EXIT_ON_CLOSE will still cause each thread's finally block to execute?
If you have no other design change choices then what you may need is a JVM shutdown hook, which can be added to run a piece of code when System.exit
is called.
Shutdown Hooks are a special construct that allow developers to plug in a piece of code to be executed when the JVM is shutting down. This comes in handy in cases where we need to do special clean up operations in case the VM is shutting down.
You can add a shutdown hook as mentioned here:
Runtime.getRuntime().addShutdownHook(Thread)
Read more about shutdown hooks here:
http://java.dzone.com/articles/know-jvm-series-2-shutdown
Word of Caution:
We must keep in mind is that it is not guaranteed that shutdown hooks will always run. If the JVM crashes due to some internal error, then it might crash down without having a chance to execute a single instruction. Also, if the O/S gives a SIGKILL (http://en.wikipedia.org/wiki/SIGKILL) signal (kill -9 in Unix/Linux) or TerminateProcess (Windows), then the application is required to terminate immediately without doing even waiting for any cleanup activities. In addition to the above, it is also possible to terminate the JVM without allowing the shutdown hooks to run by calling Runime.halt() method.