JDK-7128597 : [macosx] Program freeze when Swing is used with -XstartOnFirstThread
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: os_x
  • CPU: generic
  • Submitted: 2012-01-10
  • Updated: 2012-05-05
  • Resolved: 2012-03-05
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.
7u4 b11Fixed
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

% 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.

SUGGESTED FIX Fixed - http://hg.openjdk.java.net/jdk7u/jdk7u-osx/jdk/rev/2a8bd80fe31d

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.