JDK-4492880 : Hang in KeyboardFocusManager.shouldNativelyFocusHeavyweight() and Component.requ
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_nt,windows_2000
  • CPU: x86
  • Submitted: 2001-08-16
  • Updated: 2001-09-20
  • Resolved: 2001-08-17
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.
Other
1.4.0 beta2Fixed
Related Reports
Duplicate :  
Relates :  
Description
Updated information: it may not be necessary to follow all of 
the steps below.  A hang may occur at different points.  The bug 
may be considered fixed if you can successfully execute all 20 
steps.  

> Steps to reproduce Bug1869077 in 11.5.4 :
> ( Keyboard focus lost when minimizing the window )
>
> 1 - > Start a fresh Netscape session with 4.76 or higher on
>       a WinNT machine with JDK 1.4 plugin build 74 installed
> 2 - > Go to URL http://dnm-005.eng.sun.com:8000/OA_HTML/merlin.html
>       ( If you get a Java Plugin Secutiry Warning for the certificate
>         click on the Grant Always or Grant this Session )
> 3 - > When Oracle Application comes up
>       Username = mfg
>       Password = welcome
>       Click on Connect
> 4 - > The "Responsibility" window comes up.
>       Select "Manufacturing and Distribution Manager"
>       Click OK
> 5 - > The Navigator window comes up.
> 6 - > Minimize the Navigator window by clicking
>       on down arrow key on the left top corner of the window.
> 7 - > Restore it by clicking on the restore icon next the X
>       on the minimized window.
> 8 - > Click on Inventory-> Transactions-> Receiving -> Receipts
>       on the Navigator.
> 9 - > Organization window comes up.
>       Select "M1 Seatle Manufacturing"
>
> 10- > Minimize the "Find Expected Receipts" window by clicking on
>       down arrow on the left corner.
> 11- > Minimize the "Receipts" window in the same way
> 12- > Minimize the "Navigator" window in the same way
> 13- > Maximize the "Find Expected Receipts" window by clicking on
>       up arrow key on the minimized window.
>
> 14- > Click on Find button
> 15- > Minimize the "Receipt Header" window
> 16- > Minimize the "Receipt" window
> 17- > Change the Source Type to "Supplier" in "Find Expected Receipts"
>       Window. Click on Find button.
> 18- > Click on Details tab in Receipts window
> 19- > Minimize the Receipts window
> 20- > Minimize the Find Expected Receipts window

Name: dm26566			Date: 08/16/2001


Oracle has implemented its own GUI toolkit with UI components similar
to Swing.  We are getting a hang in a call to requestFocus() in
certain cases.  I have yet to create a Sun only testcase but
will continue to work on creating one.  I thought I should get
this filed ASAP since this bug was introduced in build 74.  It did
not exist prior to build 74.  As far as I can tell it has something to
do with a container that isFocusTraversable() that contains children
that are isFocusTraversable().  Here is the thread dump from the hang:

Full thread dump Java HotSpot(TM) Client VM (1.4.0-beta_refresh-b74 mixed mode):

"CursorIdler" prio=4 tid=0x007CC7B0 nid=0xf5 waiting on monitor [96af000..96afdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02E69918> (a oracle.ewt.timer.Periodic)
       at java.lang.Object.wait(Object.java:425)
       at oracle.ewt.timer.Timer._waitTilScheduled(Unknown Source)
       - locked <02E69918> (a oracle.ewt.timer.Periodic)
       at oracle.ewt.timer.Timer.run(Unknown Source)
       at java.lang.Thread.run(Thread.java:576)

"AWT-EventQueue-1" prio=4 tid=0x007AE240 nid=0xff runnable [959f000..959fdc0]
       at sun.awt.windows.WComponentPeer.requestFocus(Native Method)
       at java.awt.Component.requestFocusHelper(Component.java:5992)
       at java.awt.Component.requestFocus(Component.java:5821)
       at oracle.ewt.lwAWT.lwText.LWTextComponent.requestFocus(Unknown Source)
       at oracle.ewt.lwAWT.lwWindow.LWWindow$FocusTransferComp.processFocusEvent(LWWindow.java:2973)
       at java.awt.Component.processEvent(Component.java:4782)
       at java.awt.Container.processEvent(Container.java:1383)
       at oracle.ewt.lwAWT.LWComponent.processEventImpl(Unknown Source)
       at oracle.ewt.lwAWT.LWComponent.redispatchEvent(Unknown Source)
       at oracle.ewt.lwAWT.LWComponent.processEvent(Unknown Source)
       at java.awt.Component.dispatchEventImpl(Component.java:3501)
       at java.awt.Container.dispatchEventImpl(Container.java:1440)
       at java.awt.Component.dispatchEvent(Component.java:3363)
       at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1658)
       at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:692)
       at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:396)
       at java.awt.Component.dispatchEventImpl(Component.java:3392)
       at java.awt.Container.dispatchEventImpl(Container.java:1440)
       at java.awt.Component.dispatchEvent(Component.java:3363)
       at java.awt.KeyboardFocusManager.retargetFocusEvent(KeyboardFocusManager.java:2249)
       - locked <02E04B48> (a java.util.LinkedList)
       at java.awt.Component.dispatchEventImpl(Component.java:3387)
       at java.awt.Container.dispatchEventImpl(Container.java:1440)
       at java.awt.Component.dispatchEvent(Component.java:3363)
       at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3176)
       at java.awt.LightweightDispatcher.processMouseEvent(Container.java:2906)
       at java.awt.LightweightDispatcher.dispatchEvent(Container.java:2842)
       at java.awt.Container.dispatchEventImpl(Container.java:1426)
       at java.awt.Window.dispatchEventImpl(Window.java:1568)
       at java.awt.Component.dispatchEvent(Component.java:3363)
       at java.awt.EventQueue.dispatchEvent(EventQueue.java:448)
       at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:150)
       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:131)
       at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)

"TaskScheduler timer" prio=4 tid=0x007AE370 nid=0x10c waiting on monitor [955f000..955fdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02E2F218> (a oracle.ewt.timer.Timer)
       at java.lang.Object.wait(Object.java:425)
       at oracle.ewt.timer.Timer._waitTilScheduled(Unknown Source)
       - locked <02E2F218> (a oracle.ewt.timer.Timer)
       at oracle.ewt.timer.Timer.run(Unknown Source)
       at java.lang.Thread.run(Thread.java:576)

"Thread-2" prio=5 tid=0x00794430 nid=0x75 waiting on monitor [0..6fb38]

"AWT-EventQueue-0" prio=7 tid=0x00794DB0 nid=0xe6 waiting on monitor [951f000..951fdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02E037A0> (a java.awt.EventQueue)
       at java.lang.Object.wait(Object.java:425)
       at java.awt.EventQueue.getNextEvent(EventQueue.java:332)
       - locked <02E037A0> (a java.awt.EventQueue)
       at java.awt.EventDispatchThread.pumpOneEvent(EventDispatchThread.java:145)
       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:136)
       at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:131)
       at java.awt.EventDispatchThread.run(EventDispatchThread.java:99)

"AWT-Shutdown" prio=7 tid=0x00789BA0 nid=0xd6 waiting on monitor [94df000..94dfdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02DEFF88> (a java.lang.Object)
       at java.lang.Object.wait(Object.java:425)
       at sun.awt.AWTAutoShutdown.run(AWTAutoShutdown.java:262)
       - locked <02DEFF88> (a java.lang.Object)
       at java.lang.Thread.run(Thread.java:576)

"thread applet-oracle/ewt/lwAWT/demo/blaf/BLAFDemo.class" prio=4 tid=0x00786180 nid=0xe5 waiting on monitor [948f000..94
8fdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02E035E8> (a sun.applet.AppletViewerPanel)
       at java.lang.Object.wait(Object.java:425)
       at sun.applet.AppletPanel.getNextEvent(AppletPanel.java:269)
       - locked <02E035E8> (a sun.applet.AppletViewerPanel)
       at sun.applet.AppletPanel.run(AppletPanel.java:301)
       at java.lang.Thread.run(Thread.java:576)

"AWT-Windows" daemon prio=7 tid=0x00783AC0 nid=0xdc waiting for monitor entry [8fef000..8fefdc0]
       at java.awt.KeyboardFocusManager.shouldNativelyFocusHeavyweight(KeyboardFocusManager.java:1991)
       - waiting to lock <02E04B48> (a java.util.LinkedList)
       at sun.awt.windows.WToolkit.eventLoop(Native Method)
       at sun.awt.windows.WToolkit.run(WToolkit.java:222)
       at java.lang.Thread.run(Thread.java:576)

"Signal Dispatcher" daemon prio=10 tid=0x0076B5E0 nid=0x103 waiting on monitor [0..0]

"Finalizer" daemon prio=9 tid=0x00767880 nid=0x6b waiting on monitor [8c6f000..8c6fdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02DD7ED8> (a java.lang.ref.ReferenceQueue$Lock)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:114)
       - locked <02DD7ED8> (a java.lang.ref.ReferenceQueue$Lock)
       at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:129)
       at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:162)

"Reference Handler" daemon prio=10 tid=0x007664D0 nid=0x109 waiting on monitor [8c2f000..8c2fdc0]
       at java.lang.Object.wait(Native Method)
       - waiting on <02DD7F40> (a java.lang.ref.Reference$Lock)
       at java.lang.Object.wait(Object.java:425)
       at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
       - locked <02DD7F40> (a java.lang.ref.Reference$Lock)

"VM Thread" prio=5 tid=0x00765710 nid=0xfb runnable

"VM Periodic Task Thread" prio=10 tid=0x0076A960 nid=0xac waiting on monitor
"Suspend Checker Thread" prio=10 tid=0x0076A030 nid=0x102 runnable
(Review ID: 129571) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: merlin-beta2 FIXED IN: merlin-beta2 INTEGRATED IN: merlin-beta2 VERIFIED IN: merlin-beta3
17-09-2004

EVALUATION Commit to fix in merlin-beta2 (Oracle showstopper). ###@###.### 2001-08-16 Based on the stack trace, it looks like this was introduced by the fix to 4472032 in KeyboardFocusManager.java, by ###@###.###. The following lines of highly suspicious code were added to retargetFocusEvent(): ---------> grab lock on heavyweightRequests synchronized(heavyweightRequests) { /* * This code handles FOCUS_LOST event which is generated by * DefaultKeyboardFocusManager for FOCUS_GAINED. * --------> * This code based on knowledge of DefaultKeyboardFocusManager's dangerous * implementation and might be not applicable for another --------> * KeyboardFocusManager. * * Fix for 4472032 */ ... -------------> do something here evidently unrelated to heavyweightRequests } ------------> RELEASE THE LOCK ONLY TO GRAB THE SAME LOCK AGAIN!!!!!! ------------> smells suspicously like depending on the thread scheduler for timing synchronized(heavyweightRequests) { ... ------------> iterate through heavyweightRequests ... calls SendMessage, deadlock!------> currentFocusOwner.dispatchEvent(currentFocusOwnerEvent); lwFocusRequest.component. dispatchEvent(newFocusOwnerEvent); } } finally { clearingCurrentLightweightRequests = false; currentLightweightRequests = null; } } } I would suggest that we remove all of the locks here and start over. We should ask ourselves, are we modifying heavyweightRequests? Is the heavyweightRequests object managing the lock for some other state in our object? If the answer is no, then we should synchronize on the list, clone the list, then remove the lock and process the cloned list. Under no circumstances can we allow event dispatching while keeping the lock on heavyweightRequests. Since I am not familiar with this code, I do not know the reasons for the locks on heavyweightRequests here. My impression is that they are mostly unnecessary in this routine. ###@###.### 2001-08-16 Name: osR10079 Date: 08/17/2001 This bug defenitily introdused by my fix to 4472032. Both synchonization were added because Component.dispatchEvent() and therefore KFM.retargetFocusEvent() can be called on any Java thread. I made two synchronized blocks because I wanted each of these two chunks of code to execute uninterruptedly, but I don't need uninterrupted execution of their union. It may hinder the performance slightly, but it would be surely better from the code readability point of view. I synchronized on heavyweightRequests because both newFocusOwner and currentLightweightRequests could be changed in synchronized block on heavyweightRequests. I think that only second synchronized block is dangerous, since the first one doesn't contain calls which could cause deadlocks. To fix the problem we should cloning the list under synchronization and after that processing the list w/o synchonization. ###@###.### 17 Aug 2001 ====================================================================== Verified in Merlin-beta3 (Build 80 ) .This bug is fixed . ###@###.### 2001-09-20
17-09-2004

WORK AROUND Name: dm26566 Date: 08/16/2001 None. ======================================================================
17-09-2004

SUGGESTED FIX ------- KeyboardFocusManager.java ------- *** /tmp/dWbaGwX Thu Aug 16 18:10:26 2001 --- KeyboardFocusManager.java Thu Aug 16 18:09:16 2001 *************** *** 2187,2192 **** --- 2187,2196 ---- static Component newFocusOwner = null; static AWTEvent retargetFocusEvent(AWTEvent event) { + // Assert that this method is only called from the EventDispatchThread , + // so that synchronization on the lightweightRequests object is not + // necessary + dbg.assertion(EventQueue.isDispatchThread()); if (clearingCurrentLightweightRequests) { return event; } *************** *** 2193,2258 **** KeyboardFocusManager manager = getCurrentKeyboardFocusManager(); ! synchronized(heavyweightRequests) { ! /* ! * This code handles FOCUS_LOST event which is generated by ! * DefaultKeyboardFocusManager for FOCUS_GAINED. ! * ! * This code based on knowledge of DefaultKeyboardFocusManager's ! * implementation and might be not applicable for another ! * KeyboardFocusManager. ! * ! * Fix for 4472032 ! */ ! if (newFocusOwner != null && ! event.getID() == FocusEvent.FOCUS_LOST) ! { ! FocusEvent fe = (FocusEvent)event; ! if (manager.getGlobalFocusOwner() == fe.getComponent() && ! fe.getOppositeComponent() == newFocusOwner) ! { ! newFocusOwner = null; ! return event; ! } } } ! synchronized(heavyweightRequests) { ! if (currentLightweightRequests != null) { ! try { ! clearingCurrentLightweightRequests = true; ! for (Iterator iter = currentLightweightRequests.iterator() ; ! iter.hasNext(); ) ! { ! Component currentFocusOwner = manager. ! getGlobalFocusOwner(); ! if (currentFocusOwner == null) { ! // If this ever happens, a focus change has be en ! // rejected. Stop generating more focus change s. ! break; ! } ! LightweightFocusRequest lwFocusRequest = ! (LightweightFocusRequest)iter.next(); ! FocusEvent currentFocusOwnerEvent = ! new FocusEvent(currentFocusOwner, ! FocusEvent.FOCUS_LOST, ! lwFocusRequest.temporary, ! lwFocusRequest.component); ! FocusEvent newFocusOwnerEvent = ! new FocusEvent(lwFocusRequest.component, ! FocusEvent.FOCUS_GAINED, ! lwFocusRequest.temporary, ! currentFocusOwner); ! currentFocusOwner.dispatchEvent(currentFocusOwnerE vent); ! lwFocusRequest.component. ! dispatchEvent(newFocusOwnerEvent); ! } ! } finally { ! clearingCurrentLightweightRequests = false; ! currentLightweightRequests = null; } } } --- 2197,2258 ---- KeyboardFocusManager manager = getCurrentKeyboardFocusManager(); ! /* ! * This code handles FOCUS_LOST event which is generated by ! * DefaultKeyboardFocusManager for FOCUS_GAINED. ! * ! * This code based on knowledge of DefaultKeyboardFocusManager's ! * implementation and might be not applicable for another ! * KeyboardFocusManager. ! * ! * Fix for 4472032 ! */ ! if (newFocusOwner != null && ! event.getID() == FocusEvent.FOCUS_LOST) ! { ! FocusEvent fe = (FocusEvent)event; ! if (manager.getGlobalFocusOwner() == fe.getComponent() && ! fe.getOppositeComponent() == newFocusOwner) ! { ! newFocusOwner = null; ! return event; } } ! if (currentLightweightRequests != null) { ! try { ! clearingCurrentLightweightRequests = true; ! for (Iterator iter = currentLightweightRequests.iterator(); ! iter.hasNext(); ) ! { ! Component currentFocusOwner = manager. ! getGlobalFocusOwner(); ! if (currentFocusOwner == null) { ! // If this ever happens, a focus change has been ! // rejected. Stop generating more focus changes. ! break; ! } ! LightweightFocusRequest lwFocusRequest = ! (LightweightFocusRequest)iter.next(); ! FocusEvent currentFocusOwnerEvent = ! new FocusEvent(currentFocusOwner, ! FocusEvent.FOCUS_LOST, ! lwFocusRequest.temporary, ! lwFocusRequest.component); ! FocusEvent newFocusOwnerEvent = ! new FocusEvent(lwFocusRequest.component, ! FocusEvent.FOCUS_GAINED, ! lwFocusRequest.temporary, ! currentFocusOwner); ! currentFocusOwner.dispatchEvent(currentFocusOwnerEvent); ! lwFocusRequest.component. ! dispatchEvent(newFocusOwnerEvent); } + } finally { + clearingCurrentLightweightRequests = false; + currentLightweightRequests = null; } }
17-09-2004