Shutdown hooks in java

Blog

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

  • Post author: codippa
  • Post published: February 1, 2018
  • Post category: J2SE (Core Java)
  • Post comments: 0 Comments

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home3/codippac/public_html/wp-content/plugins/wp-syntax/wp-syntax.php on line 380

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home3/codippac/public_html/wp-content/plugins/wp-syntax/wp-syntax.php on line 380

Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home3/codippac/public_html/wp-content/plugins/wp-syntax/wp-syntax.php on line 380

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

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.

Читайте также:  Number in words in java

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"); } } }

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.

Share if it’s worth .

Источник

Design of the Shutdown Hooks API

On some platforms a native process can’t distinguish a shutdown due to exit from a shutdown due to termination. Other platforms provide much richer capabilities, in some cases including notification of system suspension and restart or of imminent power failure. In short, it’s impossible to generalize such information in a portable way.

Читайте также:  Серверная часть приложения php

Will shutdown hooks be run if the VM crashes?

If the VM crashes due to an error in native code then no guarantee can be made about whether or not the hooks will be run.

Why are shutdown hooks run concurrently? Wouldn’t it make more sense to run them in reverse order of registration?

Invoking shutdown hooks in their reverse order of registration is certainly intuitive, and is in fact how the C runtime library’s atexit procedure works. This technique really only makes sense, however, in a single-threaded system. In a multi-threaded system such as Java platform the order in which hooks are registered is in general undetermined and therefore implies nothing about which hooks ought to be run before which other hooks. Invoking hooks in any particular sequential order also increases the possibility of deadlocks. Note that if a particular subsystem needs to invoke shutdown actions in a particular order then it is free to synchronize them internally.

Why are hooks just threads, and unstarted ones at that? Wouldn’t it be simpler to use Runnable objects, or Beans-style event and listener patterns?

The approach taken here has two advantages over the more obvious, and more frequently suggested, callback-oriented designs based upon Runnable objects or Beans-style event listeners.

First, it gives the user complete control over the thread upon which a shutdown action is executed. The thread can be created in the proper thread group, given the correct priority, context, and privileges, and so forth.

Second, it simplifies both the specification and the implementation by isolating the VM from the hooks themselves. If shutdown actions were executed as callbacks then a robust implementation would wind up having to create a separate thread for each hook anyway in order for them to run concurrently. The specification would also have to include explicit language about how the threads that execute the callbacks are created.

Aren’t threads pretty expensive things to keep around, especially if they won’t be started until the VM shuts down?

Most implementations of the Java platform don’t actually allocate resources to a thread until it’s started, so maintaining a set of unstarted threads is actually very cheap. If you look at the internals of java.lang.Thread you can see that its various constructors just do security checks and initialize private fields. The native start() method does the real work of allocating a thread stack, etc., to get things going.

What about Personal and Embedded Java? Won’t starting threads during shutdown be too expensive on those platforms?

This API may not be suitable for the smaller Java platforms. Threads in the Java 2 Platform carry more information than threads in JDK 1.1 and p/eJava. A thread has a class loader, it may have some inherited thread-local variables, and, in the case of GUI apps, it may be associated with a specific application context. Threads will come to carry even more information as the platform evolves; for example, the security team is planning to introduce a notion of per-thread user identity in their upcoming authentication framework.

Читайте также:  Ввод вывод питон задачи

Because of all this contextual information, shutdown hooks would be harder to write and maintain if they were just Runnable objects or Beans-style event listeners. Suppose that a Runnable shutdown hook, or an equivalent event listener, needed a specific bit of thread-contextual information in order to carry out its operations. Such information could be saved in some shared location before the hook is registered. While this is merely awkward, suppose further that threads acquire some new type of contextual information in a future release. If an operation invoked by the hook also evolves to need that information then the code that registers the hook would have to be amended to save that information as well. Making hooks be threads instead of Runnables or event listeners insulates them from this sort of future change.

Okay, but won’t I have to write a lot of code just to register a simple shutdown hook?

No. Simple shutdown hooks can often be written as anonymous inner classes, as in this example:

Runtime.getRuntime().addShutdownHook(new Thread() < public void run() < database.close(); >>);

This idiom is fine as long as you’ll never need to cancel the hook, in which case you’d need to save a reference to the hook when you create it.

What about security? Can an untrusted applet register a shutdown hook?

If there is a security manager installed then the addShutdownHook and removeShutdownHook methods check that the caller’s security context permits RuntimePermission("shutdownHooks"). An untrusted applet will not have this permission, and will therefore not be able to register or de-register a shutdown hook.

What happens if a shutdown hook throws an exception and the exception is not caught?

Uncaught exceptions are handled in shutdown hooks just as in any other thread, by invoking the uncaughtException method of the thread’s ThreadGroup object. The default implementation of this method prints the exception’s stack trace to System.err and terminates the thread. Note that uncaught exceptions do not cause the VM to exit; this happens only when all non-daemon threads have finished or when the Runtime.exit method is invoked.

Why did you add the Runtime.halt method? Isn’t it pretty dangerous?

The halt method is certainly powerful, and it should be used with the utmost caution. It’s provided so that applications can insulate themselves from shutdown hooks that deadlock or run for inordinate amounts of time. It also allows applications to force a quick exit in situations where that is necessary.

What happens if finalization-on-exit is enabled? Will finalizers be run before, during, or after shutdown hooks?

Finalization-on-exit processing is done after all shutdown hooks have finished. Otherwise a hook may fail if some live objects are finalized prematurely.

Источник

Оцените статью