Java 死锁时奇怪的线程转储

Java 死锁时奇怪的线程转储,java,multithreading,deadlock,jstack,Java,Multithreading,Deadlock,Jstack,在java应用程序启动期间,我们遇到了一个奇怪的死锁。当我在应用程序上运行jstack进行调查时,我看到AWT EventQueue位于Object.wait()中,但线程仍然标记为可运行。我已经包括了线程转储的相关部分,我希望有人能对这个问题有所帮助 "AWT-EventQueue-0" prio=6 tid=0x5f0a2400 nid=0x19e4 in Object.wait() [0x6007e000] java.lang.Thread.State: RUNNABLE

在java应用程序启动期间,我们遇到了一个奇怪的死锁。当我在应用程序上运行jstack进行调查时,我看到AWT EventQueue位于Object.wait()中,但线程仍然标记为可运行。我已经包括了线程转储的相关部分,我希望有人能对这个问题有所帮助

"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)
      ...
“AWT-EventQueue-0”prio=6 tid=0x5f0a2400 nid=0x19e4在Object.wait()中[0x6007e000]
java.lang.Thread.State:可运行
位于com.ge.med.platinum.work.isu.ExamTransaction.getEAOTableLite(ExamTransaction.java:1514)
...
-锁定(java.awt.Component$AWTTreeLock)
...
“线程-63-Pool-9”优先级=6 tid=0x5f1a2800 nid=0x1f54正在等待监视器条目[0x61a9f000]
java.lang.Thread.State:阻塞(在对象监视器上)
位于java.awt.Component.setFont(Component.java:1777)
-等待锁定(java.awt.Component$AWTTreeLock)
...
“Thread-289-Pool-3”prio=6 tid=0x60afe800 nid=0x12b8等待监视器条目[0x623fe000]
java.lang.Thread.State:阻塞(在对象监视器上)
位于java.awt.Component.setFont(Component.java:1777)
-等待锁定(java.awt.Component$AWTTreeLock)
...

此外,我还注意到,其中提到访问静态变量可能会涉及。在我们的应用程序中也是如此。有问题的getEAOTableLite中的行引用了一个静态方法。

我不确定我怎么会错过它,但是如果我把堆栈跟踪读得更好一点,我会发现问题是EAOAlertManager类的静态初始化最终会调用Component.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)
“Thread-289-Pool-3”优先级=6 tid=0x60afe800 nid=0x12b8等待监视器条目[0x623fe000]
java.lang.Thread.State:阻塞(在对象监视器上)
位于java.awt.Component.setFont(Component.java:1777)
-等待锁定(java.awt.Component$AWTTreeLock)
位于java.awt.Container.setFont(Container.java:1554)
位于javax.swing.JComponent.setFont(JComponent.java:2723)
在javax.swing.LookAndFeel.installColorsAndFont(LookAndFeel.java:191)中
位于javax.swing.plaf.basic.BasicPanelUI.installDefaults(BasicPanelUI.java:49)
位于javax.swing.plaf.basic.BasicPanelUI.installUI(BasicPanelUI.java:39)
位于com.ge.med.ptk.laf.CuiPanelUI.installUI(CuiPanelUI.java:53)
位于javax.swing.JComponent.setUI(JComponent.java:662)
位于javax.swing.JPanel.setUI(JPanel.java:136)
位于javax.swing.JPanel.updateUI(JPanel.java:109)
位于javax.swing.JPanel。(JPanel.java:69)
位于javax.swing.JPanel。(JPanel.java:92)
位于javax.swing.JPanel(JPanel.java:100)
位于javax.swing.JRootPane.createGlassPane(JRootPane.java:528)
位于javax.swing.JRootPane(JRootPane.java:348)
位于javax.swing.JDialog.createRootPane(JDialog.java:611)
位于javax.swing.JDialog.dialogInit(JDialog.java:593)
位于com.ge.med.plaf.wrapper.WJDialog.dialogInit(WJDialog.java:42)
在javax.swing.JDialog(JDialog.java:545)
在javax.swing.JDialog(JDialog.java:515)
位于com.ge.med.plaf.wrapper.WJDialog(WJDialog.java:424)
在com.ge.med.platinum.gui.util.PlatinumDialog.(PlatinumDialog.java:138)
在com.ge.med.platinum.gui.util.EAOAlertManager$EAOAlertDialog上(EAOAlertManager.java:450)
在com.ge.med.platinum.gui.util.EAOAlertManager上。(EAOAlertManager.java:77)
位于com.ge.med.platinum.work.isu.ExamTransaction.getEAOTableLite(ExamTransaction.java:1514)

这篇文章似乎直截了当:
共有5页。我不知道这对您的应用程序意味着什么,但它应该会对您有所帮助。

我读对了吗,两个
组件.setFont
调用发生在事件分派线程之外?这些是你代码的结果吗?是的,它们是。。。我在发布最初的问题后注意到了这一点。我想当我第一次看到这些痕迹时,我是戴着眼罩的。你可以在下面看到我的答案。