System.exit在Linux上不是线程安全的吗?

我刚刚从Oracle JDK 1.6切换到打开JDK 1.7.0_03,在退出时我遇到了相当显着的死锁问题:

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) 

看起来你必须从AWT事件队列调用System.exit。 这是真的吗? Sun文档Runtime.exit中没有关于线程要求的文档

我遇到了其他令人惊讶的情况,只有在Linux上才需要获取AWT树锁,但是这个需要花钱。 这是一个错误,还是我错过了文档中的东西?

这取决于, runHooks方法将启动通过Runtime.addShutdownHook注册的任何钩子线程,并等待它们完成。 如果您的任何钩子线程正在锁定AWT事件线程所需的一些资源,则它们可能会导致死锁。

如果您必须在您的AWT事件线程中调用System.exit,则建议您在另一个线程中调用它,如:

  new Thread(){ public void run() { System.exit(0); } }.start(); 

不知道这是应用程序在做什么(理想情况下,这将采取SSCCE的形式)是否是运行时中的错误是不可能的。

例如,以下演示涉及System.exit()的类似的死锁。 但是,这显然是应用程序中的错误,而不是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); } }