JDK-6454631 : Focus deadlock caused by call to toolkit thread from getNativeFocusState()
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows
  • CPU: generic
  • Submitted: 2006-07-31
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b14Fixed
Related Reports
Relates :  
Description
While working with some fix I have faced the following deadlock:

----

2006-07-31 17:22:36
Full thread dump Java HotSpot(TM) Client VM (1.6.0-rc-b88 mixed mode):

"Image Fetcher 3" daemon prio=8 tid=0x0b13bc00 nid=0xcf4 in Object.wait() [0x0b84f000..0x0b84fb94]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x02a90148> (a java.util.Vector)
        at sun.awt.image.ImageFetcher.nextImage(ImageFetcher.java:114)
        - locked <0x02a90148> (a java.util.Vector)
        at sun.awt.image.ImageFetcher.fetchloop(ImageFetcher.java:167)
        at sun.awt.image.ImageFetcher.run(ImageFetcher.java:136)

"AWT-EventQueue-0" prio=6 tid=0x0b0fb000 nid=0xc14 runnable [0x0b6ef000..0x0b6efc14]
   java.lang.Thread.State: RUNNABLE
        at sun.awt.KeyboardFocusManagerPeerImpl.getNativeFocusedWindow(Native Method)
        at sun.awt.KeyboardFocusManagerPeerImpl.getCurrentFocusedWindow(KeyboardFocusManagerPeerImpl.java:27)
        at java.awt.KeyboardFocusManager.getNativeFocusedWindow(KeyboardFocusManager.java:566)
        at java.awt.KeyboardFocusManager.markClearGlobalFocusOwner(KeyboardFocusManager.java:2474)
        - locked <0x02ef7980> (a java.util.LinkedList)
        at java.awt.KeyboardFocusManager._clearGlobalFocusOwner(KeyboardFocusManager.java:551)
        at java.awt.KeyboardFocusManager.clearGlobalFocusOwner(KeyboardFocusManager.java:547)
        at java.awt.Component.doAutoTransfer(Component.java:7246)
        at java.awt.Component.autoTransferFocus(Component.java:7237)
        at java.awt.Component.autoTransferFocus(Component.java:7212)
        at java.awt.Component.hide(Component.java:1448)
        - locked <0x02efc9c8> (a java.awt.Component$AWTTreeLock)
        at javax.swing.JInternalFrame.hide(JInternalFrame.java:1744)
        at java.awt.Component.show(Component.java:1418)
        at java.awt.Component.setVisible(Component.java:1369)
        at javax.swing.JComponent.setVisible(JComponent.java:2585)
        at javax.swing.JInternalFrame.setClosed(JInternalFrame.java:809)
        at javax.swing.JOptionPane$5.propertyChange(JOptionPane.java:1523)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:339)
        at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:276)
        at java.awt.Component.firePropertyChange(Component.java:7810)
        at javax.swing.JOptionPane.setValue(JOptionPane.java:1940)
        at javax.swing.plaf.basic.BasicOptionPaneUI$ButtonActionListener.actionPerformed(BasicOptionPaneUI.java:
1184)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
        at java.awt.Component.processMouseEvent(Component.java:5999)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3240)
        at java.awt.Component.processEvent(Component.java:5764)
        at java.awt.Container.processEvent(Container.java:1984)
        at java.awt.Component.dispatchEventImpl(Component.java:4407)
        at java.awt.Container.dispatchEventImpl(Container.java:2042)
        at java.awt.Component.dispatchEvent(Component.java:4237)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4252)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3921)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3851)
        at java.awt.Container.dispatchEventImpl(Container.java:2028)
        at java.awt.Window.dispatchEventImpl(Window.java:2415)
        at java.awt.Component.dispatchEvent(Component.java:4237)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:600)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:164)
        at java.awt.Container$2.run(Container.java:2627)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:598)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:121)

"AWT-Windows" daemon prio=6 tid=0x0b0b8000 nid=0xfb8 waiting for monitor entry [0x0b45f000..0x0b45fc94]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.awt.KeyboardFocusManager.shouldNativelyFocusHeavyweight(KeyboardFocusManager.java:2282)
        - waiting to lock <0x02ef7980> (a java.util.LinkedList)
        at sun.awt.windows.WToolkit.eventLoop(Native Method)
        at sun.awt.windows.WToolkit.run(WToolkit.java:290)
        at java.lang.Thread.run(Thread.java:619)

"AWT-Shutdown" prio=6 tid=0x0b0b7400 nid=0xf04 in Object.wait() [0x0b40f000..0x0b40fd14]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x02ef4db8> (a java.lang.Object)
        at java.lang.Object.wait(Object.java:485)
        at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:259)
        - locked <0x02ef4db8> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:619)

"Java2D Disposer" daemon prio=10 tid=0x0b0c4400 nid=0x6c8 in Object.wait() [0x0b3bf000..0x0b3bfd94]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x02ef4e50> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
        - locked <0x02ef4e50> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
        at sun.java2d.Disposer.run(Disposer.java:125)
        at java.lang.Thread.run(Thread.java:619)

"Low Memory Detector" daemon prio=6 tid=0x0aaa7000 nid=0xc04 runnable [0x00000000..0x00000000]
   java.lang.Thread.State: RUNNABLE

"CompilerThread0" daemon prio=10 tid=0x0aaa5400 nid=0xf60 waiting on condition [0x00000000..0x0ad2f71c]
   java.lang.Thread.State: RUNNABLE

"Attach Listener" daemon prio=10 tid=0x0aaa3400 nid=0x9a4 runnable [0x00000000..0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x0aaa2800 nid=0xf2c waiting on condition [0x00000000..0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=8 tid=0x0aa93000 nid=0x9ac in Object.wait() [0x0ac3f000..0x0ac3fc94]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x02ef50a8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:116)
        - locked <0x02ef50a8> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:132)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10 tid=0x0aa8ec00 nid=0xdb4 in Object.wait() [0x0abef000..0x0abefd14]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x02ef5138> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:485)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
        - locked <0x02ef5138> (a java.lang.ref.Reference$Lock)

"main" prio=6 tid=0x00296000 nid=0x720 runnable [0x003ff000..0x003ffe54]
   java.lang.Thread.State: RUNNABLE
        at sun.awt.windows.WComponentPeer._requestFocus(Native Method)
        at sun.awt.windows.WComponentPeer.requestFocus(WComponentPeer.java:551)
        at java.awt.Component.requestFocusHelper(Component.java:7109)
        at java.awt.Component.requestFocusHelper(Component.java:7070)
        at java.awt.Component.requestFocus(Component.java:6890)
        at javax.swing.JComponent.requestFocus(JComponent.java:1424)
        at javax.swing.JOptionPane.showInternalOptionDialog(JOptionPane.java:1300)
        at javax.swing.JOptionPane.showInternalMessageDialog(JOptionPane.java:1068)
        at javax.swing.JOptionPane.showInternalMessageDialog(JOptionPane.java:1042)
        at javax.swing.JOptionPane.showInternalMessageDialog(JOptionPane.java:1016)
        at OptionPaneTest.main(OptionPaneTest.java:36)

"VM Thread" prio=10 tid=0x0aa8bc00 nid=0x824 runnable

"VM Periodic Task Thread" prio=10 tid=0x0aaa8800 nid=0xf1c waiting on condition

JNI global references: 1369

Heap
 def new generation   total 960K, used 292K [0x029b0000, 0x02ab0000, 0x02e90000)
  eden space 896K,  25% used [0x029b0000, 0x029e9370, 0x02a90000)
  from space 64K, 100% used [0x02a90000, 0x02aa0000, 0x02aa0000)
  to   space 64K,   0% used [0x02aa0000, 0x02aa0000, 0x02ab0000)
 tenured generation   total 4096K, used 527K [0x02e90000, 0x03290000, 0x069b0000)
   the space 4096K,  12% used [0x02e90000, 0x02f13de8, 0x02f13e00, 0x03290000)
 compacting perm gen  total 12288K, used 7512K [0x069b0000, 0x075b0000, 0x0a9b0000)
   the space 12288K,  61% used [0x069b0000, 0x071063d0, 0x07106400, 0x075b0000)
No shared spaces configured.

----

The test to reproduce the problem is attached, however it can be used to reproduce the bug only with the suggested fix for 6178755. That fix doesn't touch any of the focus issues (which are clearly seen in the stack trace above), but it makes the deadlock to happen more often.

Comments
SUGGESTED FIX +++ KeyboardFocusManager.java 2007-03-14 12:34:11.000000000 +0300 @@ -2477,34 +2477,38 @@ * because some native platforms do not support setting the native focus * owner to null. On these platforms, the obvious choice is to set the * focus owner to the focus proxy of the active Window. */ static Window markClearGlobalFocusOwner() { + // need to call this out of synchronized block to avoid possible deadlock + // see 6454631. + final Component nativeFocusedWindow = + getCurrentKeyboardFocusManager().getNativeFocusedWindow(); + synchronized (heavyweightRequests) { HeavyweightFocusRequest hwFocusRequest = getLastHWRequest(); if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) { // duplicate request return null; } - KeyboardFocusManager manager = getCurrentKeyboardFocusManager(); heavyweightRequests.add (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER); Component activeWindow = ((hwFocusRequest != null) ? Component.getContainingWindow(hwFocusRequest.heavyweight) - : manager.getNativeFocusedWindow()); + : nativeFocusedWindow); while (activeWindow != null && !((activeWindow instanceof Frame) || (activeWindow instanceof Dialog))) { - activeWindow = activeWindow.getParent(); + activeWindow = activeWindow.getParent_NoClientCode(); } - return (Window)activeWindow; + return (Window) activeWindow; } } Component getCurrentWaitingRequest(Component parent) { synchronized (heavyweightRequests) { HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
06-04-2007

EVALUATION Initially I though about possibility to not get lock on heavyweighRequest in shouldNativelyFocusHeavyweigh(), but get it earlier in requestFocus() (on user's thread. This would fix this particular deadlock. But I've noticed that we also get this lock in heavyweightButtonDown() which is called on toolkit thread from native event handler and there is no user's thread to get this lock on :( So, I decided to not change synchronization scheme. To fix the problem we should not call getNativeFocuseWindow() under heavyweightRequests lock.
14-03-2007