What happens when the JVM is terminated with System.exit(0)
or ^C
or anything of that kind? I read things like "the process is just blown away" and "every single thread is stopped", but I would like to know what happens exactly. I already know there is the shutdownHook
that somehow still gets executed, but what happens before the shutdownHooks are invoked and does anything happen after all these threads have finished?
I would like to implement such a shutdownHook
correctly and to do so I need to make the right assumptions about what might still be executed and what will not.
some code:
class SomeObject {
private boolean stopped;
SomeObject() {
stopped = false;
Thread hook = new Thread() {
@Override
public void run() {
stopped = true;
}
};
hook.setPriority(Thread.MAX_PRIORITY);
Runtime.getRuntime().addShutdownHook(hook);
}
boolean map(Iterator<Object> it) {
while(it.hasNext() && !stopped) {
writeToOtherObject(it.next());
it.remove();
}
//have calculations finished?
return !it.hasNext();
}
}
The map
function computes results that are gathered in some other object. This object should be stored in some file before everything is broken down (by normal-priority shutdownHook
s too). Does the shutdownHook
here make sense? As far I understand it, all threads are destroyed first and only then the shutdownHook
s are run (concurrently, but I assume high-priority threads are run first...) and then objects are finalized. This makes the code above rather useless, because the intention of this shutdownHook
would be to make sure no new loop is started when the shutdown has already started. Is my understanding correct and complete?
System. exit() method. This method terminates the currently running Java Virtual Machine(JVM). It takes an argument “status code” where a non zero status code indicates abnormal termination.
The Runtime. halt() can stop the shutdown sequence that has been started: Only the Runtime. halt(), which terminates the JVM forcefully, can stop the started shutdown sequence, which also means that invoking the System. exit() method will not work within a shutdown hook.
There are two ways to terminate the JVM instance from the running application: Calling the exit() method, which initiates the JVM normal shutdown sequence: run all registered shutdown hooks; run all uninvoked finalizers; then end the JVM instance. Calling the halt() method, which ends the JVM instance immediately.
If you simply close the window, it usually is only hidden, and the EDT still exists. So the JVM cannot terminate because - simple as that - a thread still exists.
Let's begin from the different ways the shutdown sequence can be initiated:
System.exit()
or Runtime.exit()
.When System.exit(int)
is called, it calls Runtime.exit()
. It checks with the security manager whether it is permitted to exit with the given status, and if so, calls Shutdown.exit()
.
If you interrupted the JVM or the system sent it the TERM signal, then by default, Shutdown.exit()
is called directly without checking with the security manager.
The Shutdown
class is an internal, package-private class in java.lang
. It has, among others, an exit()
and a halt()
methods. Its exit()
method does some stuff to prevent the hooks from being executed twice, and so on, but basically, what it does is
join
for each of them at the end. Other system hooks may run before or after the application hooks.runFinalizersOnExit
anyway.Now, contrary to your supposition, it is at stage 3 that all the threads are stopped. The halt
method is native, and I have not attempted to read the native code, but up to the moment it is called, the only code being ran is pure Java, and there is nothing that stops the threads anywhere in it. The documentation of Runtime.addShutdownHook
says, in fact:
A shutdown hook is simply an initialized but unstarted thread. 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. Note that daemon threads will continue to run during the shutdown sequence, as will non-daemon threads if shutdown was initiated by invoking the exit method.
(emphasis mine)
So you see, it is indeed part of the shutdown hook's job to tell threads that they should leave their loops and clean up.
Another misconception you have is about giving the thread a high priority. A high priority doesn't mean that the thread will run first, before all other hooks. It merely means that whenever the operating system has to make a decision which of the threads which are in "ready to run" state to give to a CPU to run, a high-priority thread will have a higher probability of "winning" - depending on the operating system's scheduling algorithm. In short, it may get a little more CPU access, but it will not - especially if you have more than one CPU core - necessarily start before other threads or complete before them.
One last thing - if you want to use a flag to tell a thread to stop working, that flag should be volatile
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With