Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when the JVM is terminated?

Tags:

java

jvm

shutdown

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.


update:

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 shutdownHooks too). Does the shutdownHook here make sense? As far I understand it, all threads are destroyed first and only then the shutdownHooks 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?

like image 638
Mr Tsjolder Avatar asked Aug 31 '15 16:08

Mr Tsjolder


People also ask

Which function terminates the running JVM?

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.

What prevents JVM from shutting down?

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.

How do I exit JVM?

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.

Why won't the JVM terminate when I close all the application windows?

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.


1 Answers

Let's begin from the different ways the shutdown sequence can be initiated:

  • The last non-daemon thread ends.
  • The JVM is interrupted (by using ctrlC or sending SIGINT).
  • The JVM is terminated (by sending SIGTERM)
  • One of the threads calls 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

  1. Run the System Hooks. The System Hooks are registered internally by JRE methods. They are ran sequentially, not in threads. The second system hook is what runs the application hooks that you have added. It starts each of them as a thread and then has a join for each of them at the end. Other system hooks may run before or after the application hooks.
  2. If finalizers are supposed to be ran prior to halting, they are ran. This should generally not even happen, as the method has been deprecated. And if the exit is with a status other than zero, it ignores the runFinalizersOnExit anyway.
  3. The JVM is halted.

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.

like image 125
RealSkeptic Avatar answered Oct 27 '22 23:10

RealSkeptic