Useful Example of a Shutdown Hook in Java

Useful example of a shutdown hook in Java?

You could do the following:

  • Let the shutdown hook set some AtomicBoolean (or volatile boolean) "keepRunning" to false
  • (Optionally, .interrupt the working threads if they wait for data in some blocking call)
  • Wait for the working threads (executing writeBatch in your case) to finish, by calling the Thread.join() method on the working threads.
  • Terminate the program

Some sketchy code:

  • Add a static volatile boolean keepRunning = true;
  • In run() you change to

    for (int i = 0; i < N && keepRunning; ++i)
    writeBatch(pw, i);
  • In main() you add:

    final Thread mainThread = Thread.currentThread();
    Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
    keepRunning = false;
    mainThread.join();
    }
    });

That's roughly how I do a graceful "reject all clients upon hitting Control-C" in terminal.


From the docs:

When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently. When all the hooks have finished it will then run all uninvoked finalizers if finalization-on-exit has been enabled. Finally, the virtual machine will halt.

That is, a shutdown hook keeps the JVM running until the hook has terminated (returned from the run()-method.

what is tha actuall use of shut down hook in java

Whenever you have some resource that must be closed (or released) on shutdown. Typical examples include connections to external databases (perhaps within a connection pool), or displaying a message to the user (as in your post), or a file handle, or any and all of the above.

Java Shutdown Hooks

Once shutdown hooks finish running the VM halts (there is actually another step in between but not relevant for this discussion).

The key here is your shutdown hook needs to live long enough for other thread to clean up, you can do this by having your shutdown hook call Thread.join(long) on the other thread, with a timeout. This will allow the shutdown hook to end after the other thread or when the specified timeout is exceeded.

Blocking the shutdown processes is usually considered to be not user friendly. Your shutdown hook should wake up or signal the other thread before joining on it, how this is done is up to you (interrupt(), wait()/notifyAll() pairing, or using a class from java.util.concurrent package.

Example:

    final Object lock = new Object(); //Lock object for synchronization.
final Thread mainThread = Thread.currentThread(); //Reference to the current thread.

Runtime.getRuntime().addShutdownHook(new Thread()
{
public void run()
{
try{
synchronized(lock){
running = false;
lock.notifyAll();
}

mainThread.join(4000);
}catch(InterruptedException){
//Interrupted.
}
}
});

synchronized(lock){
while (running && !Thread.currentThread().isInterrupted())
{
myApp.CreateMyThread();

System.out.println("Keeping busy.");
lock.wait(2000);
}
}

There are some issues with the above example, a big one being that wait() is not useful as a timer (wait() is allowed to spuriously wake up), so if you really need to have it be every 2 seconds the logic is more complicated. However, this outlines the basics of getting it to work.

Java shutdown hook

The JVM can shutdown in either an orderly or abrupt manner. A shutdown hook runs for an orderly shutdown: when the last normal thread terminates, someone calls System.exit or by other platform specific means (such as typing Ctrl-C).

Shutdown hooks will not run for an abrupt shutdown of the JVM. As you are pressing the [x] in Netbeans lower right corner, this will cause an abrupt shutdown of the JVM and this is why the shutdown hook was not started.

For example :

public class ShutdownHook {
public void attachShutDownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("exit");
}
});

}

public static void main(String[] args) {
ShutdownHook sample = new ShutdownHook();
sample.attachShutDownHook();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

If you run the above code, and let the program complete normally, you will see exit printed on the console. But if you press [x] (within 3 secs) to close it abruptly, the shutdown hook will not run and there will not be any exit printed on the console.

Collection not being iterated in a java shutdown hook

Turns out:

  • it was mainly a IO problem: unlike in the example above, i use a logger from log4j2 to print the info. log4j2 has its own shutdownHook which kills all the loggers faster than my shutdown hook since shutdown hooks are executed in parallel in the JVM. After disabling log4j2 shutdownHook, everything appeared to work as expected.
  • the hook was always executed fully (easily proven by attaching a debugger to the jvm)
  • in my particular case, i forgot to shutdown+await on my thread pools to do all the clean up i wanted to
  • i should have slept on it before posting here :/

Thank you all for the quick replies and help.

Closing I/O streams during a shutdown hook

I/O streams don't 'automatically close when the JVM is shut down'. The operating system closes any files and sockets etc that the process may have left open, but this has nothing to do with any action by the JVM. Therefore at the time the shutdown hook runs, your stream is still open.

However What you're doing is completely unnecessary. The client will receive an end of stream in any case. That's all it needs.



Related Topics



Leave a reply



Submit