Bug 507874

Summary: OpenJDK JNLP launcher violates Swing threading rules
Product: [Fedora] Fedora Reporter: Kirill Grouchnikov <kirillcool>
Component: java-1.6.0-openjdkAssignee: Lillian Angel <langel>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: low    
Version: rawhideCC: dbhole, kirillcool, langel, lkundrak, mjw, omajid
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2009-07-07 14:28:11 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Kirill Grouchnikov 2009-06-24 15:38:23 UTC
WebStart launcher violates Swing threading rules by creating the main frame off the Event Dispatch Thread.

The relevant part of the stack trace:

at test.substance.ribbon.NewCheckRibbon.main(NewCheckRibbon.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:364)
at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:600)

where test.substance.ribbon.NewCheckRibbon is the main application class. Swing threading rules state that any operation related to UI *must* run on the Event Dispatch Thread.

To reproduce, click https://substance-flamingo.dev.java.net/webstart/testRibbon.jnlp which runs under Substance look-and-feel. Substance traces the EDT violations and will throw an exception under OpenJDK - but not under Sun's JNLP launcher.

Comment 1 Omair Majid 2009-06-25 18:46:44 UTC
Hi Kirill,

Thanks for reporting this bug. I really appreciate you taking the time to test flamingo and substance with IcedTea6. I can reproduce the stack traces but I am not sure if this is a bug in IcedTea6's WebStart (Netx), Swing, or in the test program. Any help in pinpointing the problem is appreciated.

Netx doesn't know anything about the application; it simply calls the application's main method and trusts it to do the right thing. It doesn't run the application in the EDT because it has no clue what the application does - perhaps the application is a computation intensive program which wont be able to update the ui because the main thread is the EDT. So Netx runs the main() method in a normal thread. As far as I can tell (by writing a program that dumps out the stack), Sun's Web Start implementation does the same thing.

Also, Netx does not create these swing components, the test.substance.ribbon.NewCheckRibbon class does. Looking at the stack trace, I see this bit:
at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1222)
at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:1968)
at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:2044)
at test.substance.ribbon.NewCheckRibbon.main(NewCheckRibbon.java:164)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at net.sourceforge.jnlp.Launcher.launchApplication(Launcher.java:387)
at net.sourceforge.jnlp.Launcher$TgThread.run(Launcher.java:623)

Seems like setSkin calls a UI method on the normal thread and not through the EDT. Now I am not sure if this is a bug in setSkin() or if Sun's JRE automatically calls updateComponentTreeUI0 (or perhaps some other method?) on the EDT. Could you post a stack trace showing what happens when setSkin() is called using Sun's JRE?

Thanks.

Comment 2 Kirill Grouchnikov 2009-06-25 20:14:36 UTC
Hi Omair

Looking at the code of that class, the primary application window is created on the EDT (wrapped with SwingUtilities.invokeLater), but the look-and-feel is set outside it. In SubstanceLookAndFeel.setSkin i iterate over all open windows (with Window.getWindows) and update them with SwingUtilities.updateComponentTree. 

So it looks like there is another window already existing in this VM prior to the main() method being launched by the net.sourceforge.jnlp.Launcher class. Perhaps it's the WebStart console window?

Looks like i need to move the call to SubstanceLookAndFeel.setSkin to also be called on the EDT and not rely that there are no open windows prior to the main() method being called.

Let me change the code and ask the original bug submitter to verify this in his environment.

Thanks
Kirill

Comment 3 Omair Majid 2009-06-25 20:37:01 UTC
(In reply to comment #2)
> So it looks like there is another window already existing in this VM prior to
> the main() method being launched by the net.sourceforge.jnlp.Launcher class.
> Perhaps it's the WebStart console window?
Ah, yes. Netx is likely to create several windows before calling main(), including splash screens, download indicators and warning dialogs about any certificate issues.  

> Let me change the code and ask the original bug submitter to verify this in his
> environment.
Thanks for the fix.

Cheers,
Omair

Comment 4 Kirill Grouchnikov 2009-06-26 18:44:27 UTC
Omair,

The EDT-related exceptions are gone after i moved the call to SubstanceLookAndFeel.setSkin into SwingUtilities.invokeLater. However, the test application still fails under OpenJDK, with the following exceptions:

UIDefaults.getUI() failed: no ComponentUI class for:
javax.swing.JRootPane[,9,41,596x60,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,maximumSize=,minimumSize=,preferredSize=]
java.lang.Error
	at javax.swing.UIDefaults.getUIError(UIDefaults.java:728)
	at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:134)
	at javax.swing.UIDefaults.getUI(UIDefaults.java:758)
	at javax.swing.UIManager.getUI(UIManager.java:1015)
	at javax.swing.JRootPane.updateUI(JRootPane.java:482)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1231)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1222)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:1968)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:2044)
	at test.substance.ribbon.NewCheckRibbon$3.run(NewCheckRibbon.java:167)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:602)
	at
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
UIDefaults.getUI() failed: no ComponentUI class for:
javax.swing.JPanel[null.glassPane,0,0,596x60,hidden,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777217,maximumSize=,minimumSize=,preferredSize=]
java.lang.Error
	at javax.swing.UIDefaults.getUIError(UIDefaults.java:728)
	at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:134)
	at javax.swing.UIDefaults.getUI(UIDefaults.java:758)
	at javax.swing.UIManager.getUI(UIManager.java:1015)
	at javax.swing.JPanel.updateUI(JPanel.java:126)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1231)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1222)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:1968)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:2044)
	at test.substance.ribbon.NewCheckRibbon$3.run(NewCheckRibbon.java:167)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:602)
	at
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
UIDefaults.getUI() failed: no ComponentUI class for:
javax.swing.JPanel[null.contentPane,0,0,596x60,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
java.lang.Error
	at javax.swing.UIDefaults.getUIError(UIDefaults.java:728)
	at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:134)
	at javax.swing.UIDefaults.getUI(UIDefaults.java:758)
	at javax.swing.UIManager.getUI(UIManager.java:1015)
	at javax.swing.JPanel.updateUI(JPanel.java:126)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1231)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1222)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:1968)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:2044)
	at test.substance.ribbon.NewCheckRibbon$3.run(NewCheckRibbon.java:167)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:602)
	at
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
UIDefaults.getUI() failed: no ComponentUI class for:
net.sourceforge.jnlp.cache.DefaultDownloadIndicator$DownloadPanel[,0,0,596x60,layout=java.awt.GridBagLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
java.lang.Error
	at javax.swing.UIDefaults.getUIError(UIDefaults.java:728)
	at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:134)
	at javax.swing.UIDefaults.getUI(UIDefaults.java:758)
	at javax.swing.UIManager.getUI(UIManager.java:1015)
	at javax.swing.JPanel.updateUI(JPanel.java:126)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1231)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1222)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:1968)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:2044)
	at test.substance.ribbon.NewCheckRibbon$3.run(NewCheckRibbon.java:167)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:602)
	at
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
UIDefaults.getUI() failed: no ComponentUI class for:
javax.swing.JLabel[,0,0,596x18,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Downloading
Ribbon demo - Substance look and feel: 100%
Complete.,verticalAlignment=CENTER,verticalTextPosition=CENTER]
java.lang.Error
	at javax.swing.UIDefaults.getUIError(UIDefaults.java:728)
	at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:134)
	at javax.swing.UIDefaults.getUI(UIDefaults.java:758)
	at javax.swing.UIManager.getUI(UIManager.java:1015)
	at javax.swing.JLabel.updateUI(JLabel.java:273)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1231)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI0(SwingUtilities.java:1246)
	at javax.swing.SwingUtilities.updateComponentTreeUI(SwingUtilities.java:1222)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:1968)
	at org.jvnet.substance.SubstanceLookAndFeel.setSkin(SubstanceLookAndFeel.java:2044)
	at test.substance.ribbon.NewCheckRibbon$3.run(NewCheckRibbon.java:167)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:226)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:602)
	at
java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:275)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:200)
	at
java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:185)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:177)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)

I'm not sure if this is a problem with Substance or OpenJDK (this demo runs without errors on Sun JDK), and it doesn't look like it has anything to do with EDT. So this bug can be marked as CLOSED, and perhaps a new issue can be created to track the new problem (with the UIManager.getUI).

Thanks
Kirill

Comment 5 Kirill Grouchnikov 2009-07-02 04:19:09 UTC
Wasn't this bug marked as CLOSED? I can confirm that this specific problem was in my code, and not in the WebStart launcher. It was a wrong assumption based on the Sun JDK WebStart behavior.

Thanks
Kirill

Comment 6 Kirill Grouchnikov 2009-07-02 04:20:09 UTC
I've created https://bugzilla.redhat.com/show_bug.cgi?id=509301 to track the new stack traces.

Thanks
Kirill