title: What happens when shutdown hooks or finalizers don’t complete?
body: <p><em>Java Concurrency in Practice</em> says:</p>
  
  <blockquote>
    <p>In an orderly shutdown, the JVM first starts all registered shutdown hooks. Shutdown hooks are unstarted threads that are registered with Runtime.addShutdownHook. The JVM makes no guarantees on the order in which shutdown hooks are started. If any application threads (daemon or nondaemon) are still running at shutdown time, they continue to run concurrently with the shutdown process. When all shutdown hooks have completed, the JVM may choose to run finalizers if runFinalizersOnExit is true, and then halts. The JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts. <strong>If the shutdown hooks or finalizers don’t complete, then the orderly shutdown process “hangs” and the JVM must be shut down abruptly.</strong> In an abrupt shutdown, the JVM is not required to do anything other than halt the JVM; shutdown hooks will not run.</p>
  </blockquote>
  
  <p>I understand all except <strong>"If the shutdown hooks or finalizers don’t complete, then the orderly shutdown process “hangs” and the JVM must be shut down abruptly."</strong>.</p>
  
  <p><strong>What does "the orderly shutdown process “hangs”" mean?</strong> If shutdown hooks or finalizers don’t complete, it will prevent JVM from being shut down, <strong>why does it say "the JVM must be shut down abruptly"?</strong></p>
  
  <pre><code>// shutdown hook prevent JVM from being shut down
  
  package com.example.schedulerdemo;
  
  import java.util.concurrent.TimeUnit;
  
  public class EndlessShutdownHook {
  
      public static void main(String[] args) {
          Runtime.getRuntime().addShutdownHook(new Thread(() -&gt; {
              System.out.println("shutdown hook started");
              while (true) {
                  try {
                      TimeUnit.SECONDS.sleep(15);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println("loop");
              }
          }));
  
          // this thread will still run after I shutdown the application because of the endless shutdown hook
          new Thread(() -&gt; {
              while (true) {
                  try {
                      TimeUnit.SECONDS.sleep(3);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println("fixed Rate Task");
              }
          }).start();
      }
  }
  </code></pre>