Surviving Abrupt Shutdown

In many circumstances, you need a chance to do some clean-up when the user
shuts down your application. The problem is, the user does not always follow
the recommended procedure to exit. Java provides an elegant way for programmers
to execute code in the middle of the shutdown process, thus making sure your
clean-up code is always executed. This article shows how to use a shutdown hook
to guarantee that clean-up code is always run, regardless of how the user
terminates the application.

You may have code that must run just before an application completely exits.
For example, if you are writing a text editor with Swing and your application
creates a temporary edit file when it starts, this temporary file must be
deleted when the user closes your application. If you are writing a servlet
container such as Tomcat or Jetty, you must call the destroy
method of all loaded servlets before the application shuts down.

In many cases, you rely on the user to close the application as prescribed.
For instance, in the first example, you may provide a JButton
that, when clicked, runs the clean up code before exiting. Alternatively, you
may use a Window listener that listens to the
windowClosing event. Tomcat uses a batch file that can be executed
for a proper shutdown. However, you know that the user is the king; he or she can
do whatever they want with the application. He or she might be nice enough to
follow your instruction, but could just close the console or log off of the
system without first closing your application.

In Java, the virtual machine shuts down itself in response to two types of
events: first, when the application exits normally, by calling the
System.exit method or when the last non-daemon thread exits.
Second, when the user abruptly forces the virtual machine to terminate; for
example, by typing Ctrl+C or logging off from the system before
closing a running Java program.

The virtual machine starts all registered shutdown hooks, if any. Shutdown
hooks are threads registered with the Runtime. All shutdown hooks
are run concurrently until they finish.

The virtual machine calls all uninvoked finalizers, if appropriate.

In this article, we are interested in the first phase, because it allows the
programmer to ask the virtual machine to execute some clean-up code in the
program. A shutdown hook is simply an instance of a subclass of the
Thread class. Creating a shutdown hook is simple:

Write a class extending the Thread class.

Provide the implementation of your class' run method. This
method is the code that needs to be run when the application is shut down,
either normally or abruptly.

In your application, instantiate your shutdown hook class.

Register the shutdown hook with the current runtime's
addShutdownHook method.

As you may have noticed, you don't start the shutdown hook as you would
other threads. The virtual machine will start and run your shutdown hook when
it runs its shutdown sequence.

The code in Listing 1 provides a simple class called
ShutdownHookDemo and a subclass of Thread named
ShutdownHook. Note that the run method of the
ShutdownHook class simply prints the string "Shutting down" to the
console. Of course, you can insert any code that needs to be run before the
shutdown.

After instantiation of the public class, its start method is
called. The start method creates a shutdown hook and registers it
with the current runtime.

As another example, consider a simple Swing application whose class is
called MySwingApp (see Figure 1). This application creates a
temporary file when it is launched. When closed, the temporary file must be
deleted. The code for this class is given in Listing 2 on the following page.

When the user closes the application, the application must delete the
temporary file. We hope that the user will always click the Exit button--by
doing so, the shutdown method (which deletes the temporary file) will always be
called. However, the temporary file will not be deleted if the user closes the
application, by clicking the X button of the frame or by some other means.

Listing 3 offers a solution to this. It modifies the code in Listing 2 by
providing a shutdown hook. The shutdown hook class is declared as an inner
class so that it has access to all of the methods of the main class. In Listing 3,
the shutdown hook's run method calls the shutdown
method, guaranteeing that this method will be invoked when the virtual machine
shuts down.

Now, start the small application given in Listing 3. Check that the
temporary file is always deleted, even if you abruptly shut down the
application.

Summary

Sometimes we want our application to run some clean-up code prior to
shutting down. However, it is impossible to rely on the user to always quit
properly. The shutdown hook described in this article offers a solution that
guarantees that the clean-up code is run, regardless of how the user closes the
application.