How to perform an action before terminating a java application / How to use shutdown hook in java

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 :

  1. When the application is terminated by user intervention by pressing Ctrl + C on console window where it is running.
  2. 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:

  1. Create a normal java thread using a separate class (by extending java.lang.Thread) and implement its run method or create a thread using an anonymous class. This run 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.
  2. Supply this thread to addShutdownHook method of java.lang.Runtime class.
It is also possible to unregister or remove a shutdown hook by using 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.

A shutdown hook added by using an anonymous class cannot be removed since there would be no access to the thread object used while adding the hook.

Let’s tweak in

  1. A shutdown hook is just an unstarted thread which runs as soon as any of the events listed above occur.
  2. If the JVM terminates abnormally such as when an external KILL command is issued, then there is no guarantee of execution of shutdown hook.
  3. removeShutdownHook method returns true if the hook is successfully removed, false otherwise.
  4. A single application can have many shutdown hooks but their order of execution is random.
  5. It is not recommended to have any sort of user interaction inside shutdown hooks and their execution should also finish quickly.
  6. Registering a shutdown hook more than once using the same thread object will result in a java.lang.IllegalStateException as java.lang.IllegalArgumentException: Hook previously registered.
  7. 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.