Know the JVM Series – 2 – Shutdown Hooks

In this article of the Know the JVM Series, we will be looking at yet another feature that is offered by the JVM, which is not very well known, and used by the developers. Shutdown Hooks are a special construct that allows 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.

Handling this using the general constructs such as making sure that we call a special procedure before the application exists (calling System.exit(0) ) will not work for situations where the VM is shutting down due to an external reason (ex. kill request from O/S), or due to a resource problem (out of memory). As we will see soon, shutdown hooks solve this problem easily, by allowing you to provide an arbitrary code block, which will be called by the JVM when it is shutting down.

From the surface, using a shutdown hook is downright straight forward. All you have to do is simply write a class which extends the java.lang.Thread class, and provide the logic that you want to perform when the VM is shutting down, inside the public void run() method.  Then you register an instance of this class as a shutdown hook to the VM by calling Runtime.getRuntime().addShutdownHook(Thread) method. If you need to remove a previously registered shutdown hook, the Runtime class provides the removeShutdownHook(Thread) method as well.

For example,

public class TestHook {
    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                System.out.println("Shutdown Hook is running !");
            }
        });
        System.out.println("Application Terminating ...");
    }
}

That’s it, and when you run the above code, you will see that the shutdown hook is getting called by the JVM when it finishes execution of the main method. The output you will get is,

Application Terminating ...
Shutdown Hook is running !

Simple right? Yes it is.

So the question popping in your mind would be “what’s the purpose of writing an article to demonstrate something that is so simple, that could have easily fit within the 140 character limit of a tweet?”;  well, the answer is that story doesn’t end there.

While it is pretty simple to write a shutdown hook, one needs to know the internals behind the shutdown hooks to make use of those properly. Therefore, in this article, we will be exploring some of the ‘gotchas’ behind the shutdown hook design.

1. Shutdown Hooks may not be executed in some cases!

First thing to 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.

Shutdown hooks are called when the application terminates normally (when all threads finish, or when System.exit(0) is called). Also, when the JVM is shutting down due to external causes such as user requesting a termination (Ctrl+C), a SIGTERM being issued by O/S (normal kill command, without -9), or when the operating system is shutting down.

2. Once started, Shutdown Hooks can be forcibly stopped before completion.

This is actually a special case of the case explained before. Although the hook starts execution, it is possible to be terminated before it completes, in cases such as operating system shutdowns. In this type of cases, the O/S waits for a process to terminate for a specified amount of time once the SIGTERM is given. If the process does not terminate within this time limit, then the O/S terminates the process forcibly by issuing a SIGTERM (or the counterparts in Windows). So it is possible that this happens when the shutdown hook is half-way through its execution.

Therefore, it is advised to make sure that the Shutdown Hooks are written cautiously, ensuring that they finish quickly, and does not cause situations such as deadlocks. Also, the JavaDoc [1] specifically mentions that one should not perform long calculations or wait for User I/O operations in a shutdown hook.

3. You can have more than one Shutdown Hook, but their execution order is not guaranteed.

As you might have correctly guessed by the method name of addShutdownHook method (instead of setShutdownHook), you can register more than one shutdown hook. But the execution order of these multiple hooks is not guaranteed by the JVM. The JVM can execute shutdown hooks in any arbitrary order. Moreover, the JVM might execute all these hooks concurrently.

4.  You cannot register / unregister Shutdown Hooks with in Shutdown Hooks

Once the shutdown sequence is initiated by the JVM, it is not allowed to add more or remove any existing shutdown hooks. If this is attempted, the JVM throws IllegalStateException.

5. Once shutdown sequence starts, it can be stopped by Runtime.halt() only.

Once the shutdown sequence starts, only Runtime.halt() (which forcefully terminates the JVM) can stop the execution of the shutdown sequence (except for external influences such as SIGKILL). This means that calling System.exit() with in a Shutdown Hook will not work. Actually, if you call System.exit() with in a Shutdown Hook, the VM will get stuck, and you have to terminate the process forcefully.

6.  Using shutdown hooks require security permissions.

If you are using Java Security Managers, then the code which performs adding / removing of shutdown hooks need to have the shutdownHooks permission at runtime. If you invoke this method without the permission in a secure environment, then it will result in SecurityException.

7. Exceptions thrown by the Shutdown Hooks are treated same as exceptions thrown by any other code segment.

So the standard exception propagation mechanism applies here, and for uncaught exceptions, the default uncaught exception handlers will be invoked. For a detailed discussion regarding the uncaught exception handlers, refer to the Article 1 of Know the JVM Series – The Uncaught Exception Handler.

More details regarding design decisions of the Java Shutdown Hooks API are explained in the ‘Design of the Shutdown Hooks API’ article [2]. It provides the rationale for using implementations of Thread class instead of Runnable interface, and many other decisions taken by the designers of the API.

One question you might have at this point is that with so much of cases where the Shutdown Hooks may not work as expected, relying on shutdown hooks to get things done might not be a good idea. While this is logical from one side of the argument, the counter-argument would be that it is impossible to provide a 100% fool-proof solution to this problem. For example, it is possible that the machine itself crashes due to some reason, or the power goes off without leaving the machine a chance to execute any cleanup operations as expected. With these pragmatic implications, shutdown hooks are the next best thing that is available to ensure that in most of the cases, the cleanup tasks will get executed.

In conclusion, the Shutdown Hooks API provide a simple way to plug-in some arbitrary code into the shutdown sequence of the JVM. While the API may seem to be simple, one should carefully consider the consequences and implications of the actions taken by a Shutdown Hook before writing one.

References

[1] The JavaDoc for JDK 1.5 – Runtime.addShutdownHook

[2] The Design of the Shutdown Hooks API

13 comments

  1. Cool article. One thing to note is to NEVER rely on these hooks to do something critical. For example in the Runtime hook, you create a thread, but if you have an OutOfMemory where you can’t create threads, this will fail.

    1. Hi Saqib,

      Yes, what you said is correct. This will not work in such a situation. But if we look at it in another perspective, in such a situation, we will not be able to do anything from the side of Java. One such scenario is a total power failure. In that type of situations, there’s almost nothing we can do from a single applications perspective. So this will be kind of ‘last resort’ solution that we could use.

      But, like you correctly said, we should always keep in mind that this might not work as we expect in some cases.

      Thanks !

  2. “First thing to keep in mind is that it is not guaranteed that shutdown hooks will always run”…BOOM, you should’ve started the article with that and saved yourself a page of typing!

    It’s an utter waste of time to write code like this: 1) since it’s nothing but wishful coding, and you will just have to maintain it; 2) if you rely on the code then your application will fail and may/will corrupt data.

    1. Well, if you look at most of the specifications of Java, you will see that there’s hardly a guarantee. If you look at possible scenarios that would cause Shutdown Hooks not to run, there’s no other option that you could possibly use to get the same thing done. Take a native code error for example. The JVM will crash immediately, and there’s nothing you can do about it. In case of a power failure, entire machine will be down without leaving you a chance to do anything about it. Think about a blue screen of death in windows, or a kernel panic in unix. Those type of situations will not allow you to do any sort of clean up at all.

      Software has always been, and always will be (for a foreseeable future) unreliable in such type of situations. So it is only natural that there is no way for the designers of this API (or any such API for that matter) to provide guarantees about being able to execute.

      With the absence of a better solution (again, software based), Shutdown Hook API is the solution that one could employ to handle this type of situations. If you could take a look at many open source middle-ware projects out there (JBoss, Tomcat, you name it), most of those use shutdown hooks to handle various things. For example, when you hit Ctrl+C on a JBoss execution console, the shutdown hooks get activated to do clean ups.

      Yes, it could be wishful coding, but this works all around the world in all most all enterprise Java applications, since the application servers that host those rely on this.

  3. Yohan hats off to you!!!

    This article is so clear and more explanatory about Hook towards servers.

    I tried several document even though in official doc but no use.

    Thanks again for great help.

    U Rocks!!!!!!!!!!!

  4. public static void main(String[] args) {
    // TODO Auto-generated method stub
    Runtime.getRuntime().addShutdownHook(new Thread(){
    @Override
    public void run() {
    System.exit(0);
    System.out.println(“do hook”);

    }
    });
    }

    prints nothing, “5. Once shutdown sequence starts, it can be stopped by Runtime.halt() only.” seems to be wrong

    1. It prints nothing because the call to System.exit() blocks the thread indefinitely, which will eventually be terminated when the VM shutdown sequence completes. So your call to System.exit() will be blocked, and it will never reach the sysout. But it does not affect the shutdown sequence – it affects only that particular thread.

      Here’s the JavaDoc reference that explains this behaviour: http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exit(int)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>