6

I've just switched from Oracle JDK 1.6, to Open JDK 1.7.0_03, and I've hit a rather remarkable deadlock on exit:

java.lang.Thread.State: WAITING (on object monitor)
 at java.lang.Object.wait(Native Method)
 at java.lang.Thread.join(Thread.java:1258)
 - locked <0x8608dda0> (a sun.awt.X11.XToolkit$1$1)
 at java.lang.Thread.join(Thread.java:1332)
 at java.lang.ApplicationShutdownHooks.runHooks(ApplicationShutdownHooks.java:106)
 at java.lang.ApplicationShutdownHooks$1.run(ApplicationShutdownHooks.java:46)
 at java.lang.Shutdown.runHooks(Shutdown.java:123)
 at java.lang.Shutdown.sequence(Shutdown.java:167)
 at java.lang.Shutdown.exit(Shutdown.java:212)
 - locked <0x8603df28> (a java.lang.Class for java.lang.Shutdown)
 at java.lang.Runtime.exit(Runtime.java:107)
 at java.lang.System.exit(System.java:960)

It appears that you must call System.exit from the AWT event queue. Is this for real? There is no documentation of a thread requirement in the Sun docs Runtime.exit

I've hit other surprising cases where getting the AWT tree lock is required only on Linux, but this one takes the cake. Is this a bug, or have I just missed something in the documentation?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Joshua Smith
  • 3,689
  • 4
  • 32
  • 45
  • 2
    Got an SSCCE (http://sscce.org/) demonstrating the deadlock? – NPE Apr 04 '13 at 14:47
  • 1
    The `System.exit` method forces termination of all threads in the Java virtual machine. You are not fixing the mentioned deadlock problem by using System.exit, you are stopping the program before the deadlock occurs. When you stop normally, your other threads continue on without the assistance of the main thread and apparently they can't do so without it. – Eric Leschinski Apr 04 '13 at 14:57

2 Answers2

1

It depends, the runHooks method will start any hook threads registered through Runtime.addShutdownHook and wait for them to be finished. If any of your hook threads is locking some resources that the AWT event thread is requiring too, they may cause dead lock.

If you have to call System.exit in your AWT event thread,I suggest you call it in another thread like:

 new Thread(){
            public void run() {
                System.exit(0);
            }
   }.start();
BlackJoker
  • 3,099
  • 2
  • 20
  • 27
1

It is impossible to say whether this is a bug in the runtime without knowing more about what the application is doing (ideally, this would take the form of an SSCCE).

For example, the following demonstrates a similar deadlock involving System.exit(). However, it is clearly a bug in the application, not in System.exit():

public class OhNo {

    final static Object lock = new Object();

    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    for (;;) {
                    }
                }
            }
        }).start();
        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            public void run() {
                synchronized (lock) {
                    System.out.println("in shutdown hook");
                }
            }
        }));
        System.out.println("about to call System.exit()");
        System.exit(0);
    }
}
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • AWT-EventQueue-0 is calling me, and I'm grabbing a lock on an object O. O is busy so the AWT-EventQueue-0 is blocked waiting. O is calling System.exit(), and on Linux, this waits for the AWT tree lock, which, of course, is waiting on O. Hence, deadlock. Anyway, I guess given that there are these shutdown hooks that could be doing any weird thing, the right answer is to create a new thread to shut down, as suggested by Spring.Rush. That seems very robust. – Joshua Smith Apr 04 '13 at 15:06