Scenario
Suppose your application starts a process (a server embedded in the application, let’s say). The application may be running from a command line interface or a GUI. Now, you want that whenever user terminates the application either by typing Ctrl + C(control and c keys pressed together) on command line or pressing close button on the application GUI, the process started by the application is also terminated.
Shutdown Hook is the solution
A shutdown hook is a piece of code which executes before an application terminates. Java provides a mechanism to apply shutdown hooks in an application. This shutdown hook is executed in below 2 cases :
- When the application is terminated by user intervention by pressing Ctrl + C on console window where it is running.
- When
System.exit()
is called from within the application.
How to apply shutdown hook
A shutdown hook is a separate thread which runs only when above 2 events occur and it is created using java.lang.Runtime
class of java library. Creating a shutdown hook involves following steps:
- Create a normal java thread using a separate class (by extending
java.lang.Thread)
and implement itsrun
method or create a thread using an anonymous class. Thisrun
method should contain the task which you want to perform during shutdown such as killing a process, closing a file or a database connection etc. - Supply this thread to
addShutdownHook
method ofjava.lang.Runtime
class.
removeShutdown
method of java.lang.Runtime
class. This method takes the thread object which was supplied as argument while adding the hook.
Scenario 1 : When System.exit() is called
Create a class which extends java.lang.Thread
class and implement its run method. This method should have all the code which needs to be executed as a part of shutdown process. Pass this thread to the addShutdownHook
method if java.lang.Runtime
class as shown below.
public class ShutDownHookDemo {
public static void main(String[] args) {
// create thread object
ShutDownTask shutDownTask = new ShutDownTask();
// add shutdown hook
Runtime.getRuntime().addShutdownHook(shutDownTask);
// exit application
System.exit(0);
}
/**
* Class having shutdown steps
*
*/
private static class ShutDownTask extends Thread {
@Override
public void run() {
System.out.println("Performing shutdown");
}
}
}
When the above code is executed, following is the output
Performing shutdown
Note that when System.exit(0)
is called, the statement written inside the shutdown hook gets printed. In actual applications, it will have a much complex code to perform actual shutdown operations.
Scenario 2 : When Ctrl + C is pressed
Consider the following code where a dummy infinite loop has been created. In real applications, this will be replaced by the application logic which takes some time to execute. Suppose this application is running on command line and user presses Control + C in between. Below program registers a shutdown hook which is executed as soon as Ctrl and C keys are pressed. See the output of execution after the code.
public class ShutDownHookDemo {
public static void main(String[] args) {
// create thread object
ShutDownTask shutDownTask = new ShutDownTask();
// add shutdown hook
Runtime.getRuntime().addShutdownHook(shutDownTask);
System.out.println("Going into infinite loop...");
// infinite loop. Real applications will have some long running logic
// here
while (true) {
//application logic
}
}
/**
* Class having shutdown steps
*
*/
private static class ShutDownTask extends Thread {
@Override
public void run() {
System.out.println("Performing shutdown");
}
}
}
Output
The program is stuck in an infinite loop. When Ctrl-c is pressed at the console window, the registered shutdown hook is executed before application termination.
Shutdown hook using Anonymous Thread class
In both the above examples, a shutdown hook was created as a separate implementation class of java.lang.Thread
but it is also possible without creating a separate class and creating it anonymously. Code is shown below.
public class ShutDownHookDemo {
public static void main(String[] args) {
// create shutdown hook with anonymous implementation
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Performing shutdown");
}
});
System.out.println("Going into infinite loop...");
// infinite loop. Real applications will have some long running logic
// here
while (true) {
// application logic
}
}
}
Behavior of shutdown hook created using this approach is the same.
Let’s tweak in
- A shutdown hook is just an unstarted thread which runs as soon as any of the events listed above occur.
- If the JVM terminates abnormally such as when an external KILL command is issued, then there is no guarantee of execution of shutdown hook.
removeShutdownHook
method returnstrue
if the hook is successfully removed, false otherwise.- A single application can have many shutdown hooks but their order of execution is random.
- It is not recommended to have any sort of user interaction inside shutdown hooks and their execution should also finish quickly.
- Registering a shutdown hook more than once using the same thread object will result in a
java.lang.IllegalStateException
asjava.lang.IllegalArgumentException: Hook previously registered.
- Trying to add a new shutdown hook from another shutdown hook is not permitted and throws an exception as
java.lang.IllegalStateException: Shutdown in progress
. This is because you cannot add a new shutdown hook once a shutdown process has started.