- PR -

getTreeLock() のロックが取れずデッドロック

投稿者投稿内容
まさ
ベテラン
会議室デビュー日: 2002/11/15
投稿数: 74
投稿日時: 2004-06-08 14:55
まさです。

前回のアプレットとは別の自作アプリで
おそらく同様の現象であろうデッドロックが出まして、
スレッドダンプが取れました。

コード:
Full thread dump Java HotSpot(TM) Client VM (1.4.1-b21 mixed mode):

"showWindowThread" prio=7 tid=0x0F871408 nid=0xe74 in Object.wait() [fc7f000..fc7fd88]
	at java.lang.Object.wait(Native Method)
	- waiting on <0328EF38> (a javax.swing.text.PlainDocument)
	at java.lang.Object.wait(Object.java:426)
	at javax.swing.text.AbstractDocument.readLock(AbstractDocument.java:1385)
	- locked <0328EF38> (a javax.swing.text.PlainDocument)
	at javax.swing.plaf.basic.BasicTextUI.getPreferredSize(BasicTextUI.java:796)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1272)
	at javax.swing.JTextField.getPreferredSize(JTextField.java:406)
	at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:564)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.preferredSize(Container.java:1175)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.getPreferredSize(Container.java:1159)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1274)
	at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:569)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.preferredSize(Container.java:1175)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.getPreferredSize(Container.java:1159)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1274)
	at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:574)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.preferredSize(Container.java:1175)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.getPreferredSize(Container.java:1159)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1274)
	at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:564)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.preferredSize(Container.java:1175)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.getPreferredSize(Container.java:1159)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1274)
	at javax.swing.JRootPane$RootLayout.preferredLayoutSize(JRootPane.java:816)
	at java.awt.Container.preferredSize(Container.java:1175)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.getPreferredSize(Container.java:1159)
	at javax.swing.JComponent.getPreferredSize(JComponent.java:1274)
	at java.awt.BorderLayout.preferredLayoutSize(BorderLayout.java:564)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.preferredSize(Container.java:1175)
	- locked <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.getPreferredSize(Container.java:1159)
	at java.awt.Window.pack(Window.java:430)
	at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.openDetailWindow(TopPanel.java:1125)
	at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.access(TopPanel.java:1064)
	at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.run(TopPanel.java:562)
	- locked <0324CBE0> (a jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel)

"DestroyJavaVM" prio=5 tid=0x00034D48 nid=0xd50 waiting on condition [0..7fad8]

"Java2D Disposer" daemon prio=10 tid=0x0AD75BF8 nid=0xa4c in Object.wait() [b0ef000..b0efd88]
	at java.lang.Object.wait(Native Method)
	- waiting on <02FF00E8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
	- locked <02FF00E8> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
	at sun.java2d.Disposer.run(Disposer.java:97)
	at java.lang.Thread.run(Thread.java:536)

"AWT-EventQueue-0" prio=7 tid=0x0AD22950 nid=0x674 waiting for monitor entry [b0af000..b0afd88]
	at java.awt.Component.invalidate(Component.java:2117)
	- waiting to lock <02F60C58> (a java.awt.Component$AWTTreeLock)
	at java.awt.Container.invalidate(Container.java:1035)
	at javax.swing.JComponent.revalidate(JComponent.java:4388)
	at javax.swing.plaf.basic.BasicTextUI$RootView.preferenceChanged(BasicTextUI.java:1290)
	at javax.swing.text.View.preferenceChanged(View.java:298)
	at javax.swing.text.PlainView.updateDamage(PlainView.java:522)
	at javax.swing.text.PlainView.insertUpdate(PlainView.java:407)
	at javax.swing.text.FieldView.insertUpdate(FieldView.java:264)
	at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1486)
	at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1720)
	at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:184)
	at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)
	at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:706)
	at javax.swing.text.PlainDocument.insertString(PlainDocument.java:114)
	at javax.swing.text.JTextComponent.setText(JTextComponent.java:1383)
	at jp.co.xxxxx.kagorg.tool.messagechecker.DetailPanel.setStatusView(DetailPanel.java:459)
	at jp.co.xxxxx.kagorg.tool.messagechecker.DetailPanel.access(DetailPanel.java:424)
	at jp.co.xxxxx.kagorg.tool.messagechecker.DetailPanel.run(DetailPanel.java:945)
	- locked <02A958D8> (a jp.co.xxxxx.kagorg.tool.messagechecker.DetailPanel)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:448)
	at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:197)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:144)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)

"AWT-Windows" daemon prio=7 tid=0x0AD2DCA0 nid=0xaac runnable [af8f000..af8fd88]
	at sun.awt.windows.WToolkit.eventLoop(Native Method)
	at sun.awt.windows.WToolkit.run(WToolkit.java:253)
	at java.lang.Thread.run(Thread.java:536)

"AWT-Shutdown" prio=5 tid=0x0ACFC8D0 nid=0xbf8 in Object.wait() [af4f000..af4fd88]
	at java.lang.Object.wait(Native Method)
	- waiting on <02F93038> (a java.lang.Object)
	at java.lang.Object.wait(Object.java:426)
	at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:259)
	- locked <02F93038> (a java.lang.Object)
	at java.lang.Thread.run(Thread.java:536)

"TimerQueue" daemon prio=5 tid=0x009F90A8 nid=0xb94 in Object.wait() [aeaf000..aeafd88]
	at java.lang.Object.wait(Native Method)
	- waiting on <02F90E68> (a javax.swing.TimerQueue)
	at javax.swing.TimerQueue.run(TimerQueue.java:231)
	- locked <02F90E68> (a javax.swing.TimerQueue)
	at java.lang.Thread.run(Thread.java:536)

"Signal Dispatcher" daemon prio=10 tid=0x009E8808 nid=0xf14 waiting on condition [0..0]

"Finalizer" daemon prio=9 tid=0x0003E9A8 nid=0xc44 in Object.wait() [ab6f000..ab6fd88]
	at java.lang.Object.wait(Native Method)
	- waiting on <02F609E0> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
	- locked <02F609E0> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10 tid=0x0003D578 nid=0xdc in Object.wait() [ab2f000..ab2fd88]
	at java.lang.Object.wait(Native Method)
	- waiting on <02F60A48> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:426)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:113)
	- locked <02F60A48> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=5 tid=0x009E52F0 nid=0xe80 runnable 

"VM Periodic Task Thread" prio=10 tid=0x009E71E0 nid=0xc94 waiting on condition 
"Suspend Checker Thread" prio=10 tid=0x009E7E48 nid=0xed0 runnable 



(一部、パッケージ名を編集しています。)

AWT-EventQueue-0 でデッドロックしています。
このダンプから何かわかりますでしょうか?

とりあえず、イベントディスパッチスレッド以外から
Swingコンポーネントにアクセスしていそうなところを洗い出しています。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-06-08 15:27
unibon です。こんにちわ。

引用:

まささんの書き込み (2004-06-08 14:55) より:
AWT-EventQueue-0 でデッドロックしています。
このダンプから何かわかりますでしょうか?

とりあえず、イベントディスパッチスレッド以外から
Swingコンポーネントにアクセスしていそうなところを洗い出しています。



スレッドダンプを見ると、独自に showWindowThread というスレッドを作られて、そのスレッドで

> at java.awt.Window.pack(Window.java:430)
> at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.openDetailWindow(TopPanel.java:1125)
> at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.access(TopPanel.java:1064)
> at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.run(TopPanel.java:562)
> - locked <0324CBE0> (a jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel)

のように pack していることが分かります。pack などのメソッドは GUI スレッド(通常は AWT-EventQueue-0 という名前のスレッド)で呼ぶ必要があります。すなわち、マルチスレッド用に new Thread(); したスレッドからは、通常は pack などのメソッドを呼べません。
簡便な対処としては SwingUtilities.invokeLater でディスパッチすればうまく行くことが多いです。と言っても、マルチスレッドにしたのはそれなりに理由があるためだと思いますので、必ずしもこれでうまくいくとは限りません。しかし、デッドロックは出なくなることは確実です(デッドロックになりようがないので)。
まさ
ベテラン
会議室デビュー日: 2002/11/15
投稿数: 74
投稿日時: 2004-06-08 21:42
まさです。

引用:

スレッドダンプを見ると、独自に showWindowThread というスレッドを作られて、そのスレッドで

> at java.awt.Window.pack(Window.java:430)
> at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.openDetailWindow(TopPanel.java:1125)
> at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.access(TopPanel.java:1064)
> at jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel.run(TopPanel.java:562)
> - locked <0324CBE0> (a jp.co.xxxxx.kagorg.tool.messagechecker.TopPanel)

のように pack していることが分かります。pack などのメソッドは GUI スレッド(通常は AWT-EventQueue-0 という名前のスレッド)で呼ぶ必要があります。すなわち、マルチスレッド用に new Thread(); したスレッドからは、通常は pack などのメソッドを呼べません。
簡便な対処としては SwingUtilities.invokeLater でディスパッチすればうまく行くことが多いです。と言っても、マルチスレッドにしたのはそれなりに理由があるためだと思いますので、必ずしもこれでうまくいくとは限りません。しかし、デッドロックは出なくなることは確実です(デッドロックになりようがないので)。



あ、なるほど。。。
「侍」で見たら、"AWT-EventQueue-0" だけ赤くなっていたので
そっちに気をとられていました。。。
とりあえず、該当箇所を invokeLater にしてみました。

今回のダンプのおかげで、
次回デッドロック時には解決への糸口が見えそうな気がします。

ありがとうございます!!
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-06-08 22:16
>「侍」で見たら、"AWT-EventQueue-0" だけ赤くなっていたので
すいません・・・。アイドルスレッドはグレーで表示するようになっているんです。
赤く表示される" waiting for monitor entry"状態のスレッドがあれば必ずオブジェクトをロックしているスレッドがペアでありますので併せて確認しましょう。

スキルアップ/キャリアアップ(JOB@IT)