死锁上奇怪的线程转储

死锁上奇怪的线程转储

问题描述:

在我们的java应用程序启动过程中,我们遇到了一个奇怪的死锁。当我在应用程序上运行jstack进行调查时,发现AWT-EventQueue在Object.wait()中,但该线程仍被标记为RUNNABLE。我已经包含了线程转储的相关部分,并且我希望有人能够解释这个问题。死锁上奇怪的线程转储

"AWT-EventQueue-0" prio=6 tid=0x5f0a2400 nid=0x19e4 in Object.wait() [0x6007e000] 
     java.lang.Thread.State: RUNNABLE 
     at com.ge.med.platinum.work.isu.ExamTransaction.getEAOTableLite(ExamTransaction.java:1514) 
      ... 
      - locked <0x1fc87448> (a java.awt.Component$AWTTreeLock) 
      ... 

"Thread-63-Pool-9" prio=6 tid=0x5f1a2800 nid=0x1f54 waiting for monitor entry [0x61a9f000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at java.awt.Component.setFont(Component.java:1777) 
    - waiting to lock <0x1fc87448> (a java.awt.Component$AWTTreeLock) 
     ... 

"Thread-289-Pool-3" prio=6 tid=0x60afe800 nid=0x12b8 waiting for monitor entry [0x623fe000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at java.awt.Component.setFont(Component.java:1777) 
    - waiting to lock <0x1fc87448> (a java.awt.Component$AWTTreeLock) 
     ... 

此外,我注意到this thread,其中提到,访问一个静态变量可能参与。我们的应用也是如此。问题中的getEAOTableLite中的行引用了静态方法。

+0

我读的是这两个'Component.setFont'调用是否发生在事件派发线程之外的权利?那是你的代码的结果吗? – kschneid 2010-09-16 16:32:22

+0

是的,他们是......我在发布最初的问题后注意到了这一点。我想我第一次通过跟踪时看到了自己的盲点。你可以在下面看到我的答案。 – 2010-09-16 16:37:59

我不知道我是如何错过它的,但是如果我已经更好地读了一下堆栈跟踪,我会发现问题是EAOAlertManager类的静态初始化将事件全部调用组件.setFont()方法,它被AWT-EventQueue阻塞(在EventQueue之外调用setFont()是非法的)。 EventQueue最后返回到ExamTransaction.getEAOTableLite,这意味着它将再次引用EAOAlertManager类,导致它等待类完成加载。但EAOAlertManager类正在等待EventQueue。我的朋友们,这是一个僵局。

"Thread-289-Pool-3" prio=6 tid=0x60afe800 nid=0x12b8 waiting for monitor entry [0x623fe000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at java.awt.Component.setFont(Component.java:1777) 
    - waiting to lock <0x1fc87448> (a java.awt.Component$AWTTreeLock) 
    at java.awt.Container.setFont(Container.java:1554) 
    at javax.swing.JComponent.setFont(JComponent.java:2723) 
    at javax.swing.LookAndFeel.installColorsAndFont(LookAndFeel.java:191) 
    at javax.swing.plaf.basic.BasicPanelUI.installDefaults(BasicPanelUI.java:49) 
    at javax.swing.plaf.basic.BasicPanelUI.installUI(BasicPanelUI.java:39) 
    at com.ge.med.ptk.laf.CuiPanelUI.installUI(CuiPanelUI.java:53) 
    at javax.swing.JComponent.setUI(JComponent.java:662) 
    at javax.swing.JPanel.setUI(JPanel.java:136) 
    at javax.swing.JPanel.updateUI(JPanel.java:109) 
    at javax.swing.JPanel.<init>(JPanel.java:69) 
    at javax.swing.JPanel.<init>(JPanel.java:92) 
    at javax.swing.JPanel.<init>(JPanel.java:100) 
    at javax.swing.JRootPane.createGlassPane(JRootPane.java:528) 
    at javax.swing.JRootPane.<init>(JRootPane.java:348) 
    at javax.swing.JDialog.createRootPane(JDialog.java:611) 
    at javax.swing.JDialog.dialogInit(JDialog.java:593) 
    at com.ge.med.plaf.wrapper.WJDialog.dialogInit(WJDialog.java:42) 
    at javax.swing.JDialog.<init>(JDialog.java:545) 
    at javax.swing.JDialog.<init>(JDialog.java:515) 
    at com.ge.med.plaf.wrapper.WJDialog.<init>(WJDialog.java:424) 
    at com.ge.med.platinum.gui.util.PlatinumDialog.<init>(PlatinumDialog.java:138) 
    at com.ge.med.platinum.gui.util.EAOAlertManager$EAOAlertDialog.<init>(EAOAlertManager.java:450) 
    at com.ge.med.platinum.gui.util.EAOAlertManager.<clinit>(EAOAlertManager.java:77) 
    at com.ge.med.platinum.work.isu.ExamTransaction.getEAOTableLite(ExamTransaction.java:1514) 

这篇文章似乎是直接切入正题: http://www.javaworld.com/javaworld/jw-04-1999/jw-04-toolbox.html 有5页。我不知道这对你的应用意味着什么,但它应该对你有所帮助。