United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7128597 [macosx] Program freeze when Swing is used with -XstartOnFirstThread
JDK-7128597 : [macosx] Program freeze when Swing is used with -XstartOnFirstThread

Details
Type:
Bug
Submit Date:
2012-01-10
Status:
Closed
Updated Date:
2012-05-05
Project Name:
JDK
Resolved Date:
2012-03-05
Component:
client-libs
OS:
os_x
Sub-Component:
2d
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
7
Fixed Versions:
7u4 (b11)

Related Reports

Sub Tasks

Description
Migrated from http://java.net/jira/browse/MACOSX_PORT-784:

------------------------------------------------------------
There seems to be a deadlock when using Swing with -XstartOnFirstThread. Here's an example program:

import javax.swing.UIManager;
public class Java7Test {
public static void main( String[] argv ) throws InterruptedException { System.out.println( "Before Swing" ); UIManager.getColor( "Panel.background" ); System.out.println( "After Swing" ); System.exit( 0 ); }
}

This works correctly:

% java Java7Test
Before Swing
After Swing

This never finishes:

% java -XstartOnFirstThread Java7Test
Before Swing
^C

% java -version
openjdk version "1.7.0-b222"
OpenJDK Runtime Environment (build 1.7.0-b222-20111220)
OpenJDK 64-Bit Server VM (build 21.0-b17, mixed mode)

Switching to Apple's Java 1.6 works:
% java -version
java version "1.6.0_29"
Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-11M3527)
Java HotSpot(TM) 64-Bit Server VM (build 20.4-b02-402, mixed mode)

% java -XstartOnFirstThread Java7Test
Before Swing
2011-12-29 07:24:35.096 java[1287:2007] [Java CocoaComponent compatibility mode]: Enabled
2011-12-29 07:24:35.096 java[1287:2007] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
After Swing

Debugging the above program (run with 1.7.0) in Eclipse shows the following stacktrace when it is frozen/deadlocked:

Thread [main] (Suspended)
Object.wait(long) line: not available [native method]
OGLRenderQueue$QueueFlusher(Object).wait() line: 503
OGLRenderQueue$QueueFlusher.flushNow() line: 167
OGLRenderQueue$QueueFlusher.flushAndInvokeNow(Runnable) line: 180
OGLRenderQueue.flushAndInvokeNow(Runnable) line: 125
CGLGraphicsConfig.getConfig(CGraphicsDevice, int) line: 139
CGraphicsDevice.<init>(int) line: 52
CGraphicsEnvironment.initDevices() line: 146
CGraphicsEnvironment.<init>() line: 103
NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]
NativeConstructorAccessorImpl.newInstance(Object[]) line: 57
DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45
Constructor<T>.newInstance(Object...) line: 525
Class<T>.newInstance0() line: 372
Class<T>.newInstance() line: 325
GraphicsEnvironment.createGE() line: 109
GraphicsEnvironment.getLocalGraphicsEnvironment() line: 81
RepaintManager.<clinit>() line: 201
UIManager.initialize() line: 1446 [local variables unavailable]
UIManager.maybeInitialize() line: 1418
UIManager.getDefaults() line: 653
UIManager.getColor(Object) line: 695
Java7Test.main(String[]) line: 6

I need to use -XstartOnFirstThread because I'm using SWT. Swing only comes into play because I'm using JFreeChart with its SWT components as well. Drawing in JFreeChart SWT components is done with SWT GC, but there are some initializations and static components that use Swing.

If I can help with testing or providing more information, please let me know.

                                    

Comments
SUGGESTED FIX

Fixed - http://hg.openjdk.java.net/jdk7u/jdk7u-osx/jdk/rev/2a8bd80fe31d
                                     
2012-01-20
EVALUATION

Mike Swingler added a comment - 10/Jan/12 08:12 PM

If any of that initialization touches AppKit classes or has objects that inherit from AppKit classes (like NSOpenGLContext), calling -[super init] from a non-AppKit thread is still a threading violation. If +[NSThread isMainThread] returns true, you can simply call your initializer directly, instead of punting it onto the main thread.

Dmitry Cherepanov added a comment - 11/Jan/12 10:00 AM

Here's a fix to prevent the deadlock: http://cr.openjdk.java.net/~dcherepanov/7128597/webrev.0/

the fix includes

 - the addition of +[NSThread isMainThread] was done at Mike's suggestion
 - not calling the getCGLConfigInfo method on the queue flusher thread to ensure that the native method is called on the AppKit (current) thread. I tried to understand the reason for executing the getCGLConfigInfo method on the queue flusher thread and I found the following bug: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6236067
which explains:

"These problems seem to be specific to ATI's drivers on Windows, when attempting to render from a thread other than the one on which everything (i.e. the GraphicsConfig and the context) were created"

With and without the patch applied, the initialization is executed on the AppKit thread and it should be a safe change.
                                     
2012-01-20



Hardware and Software, Engineered to Work Together