Java Static-block Shutdown Hook with System.exit

deadlock, java, static

Solution

It is important that classes are not accessed concurrently whilst initialising, so a lock is held.

I guess what is happening in the first case is:

- The main thread holds the initialisation lock for `Main`.

- Whilst holding the lock, `System.exit` blocks as it does not return.

- The shutdown hook executes.

- The shutdown tries to access the `Main` class to read a field, but blocks as the class is initialising.

Hence the deadlock. It's a little clearer if you write `if (a == null);` as `if (Main.a == null);`.

In the second case, the value is copied and therefore the shutdown hook does not need to access the `Main` class.

Moral: Don't mix threads and class initialisation. Gafter and Bloch's Java Puzzlers book has more on this.

Problem

This code will deadlock: ``` public class Main { static public final Object a = new Object(); static { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { if (a == null); } }); System.exit(0); } static public void main(final String[] args) {} } ``` This code will exit normally: ``` public class Main { static public final Object a = new Object(); static { final Object aa = a; Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { if (aa == null); } }); System.exit(0); } static public void main(final String[] args) {} } ``` What is happening?

Original source