diff --git a/src/macosx/native/sun/awt/CGraphicsEnv.m b/src/macosx/native/sun/awt/CGraphicsEnv.m index 735e70bc4a21052391e3c057827bab93033c107e..c8044d111444562bc932283cc8c35ba5f3d1f872 100644 --- a/src/macosx/native/sun/awt/CGraphicsEnv.m +++ b/src/macosx/native/sun/awt/CGraphicsEnv.m @@ -26,6 +26,7 @@ #import #import "jni_util.h" +#import "ThreadUtilities.h" #import "LWCToolkit.h" #import "AWT_debug.h" @@ -133,17 +134,20 @@ static void displaycb_handle { if (flags == kCGDisplayBeginConfigurationFlag) return; - JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { - JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; - - jobject graphicsEnv = [wrapper jObjectWithEnv:env]; - if (graphicsEnv == NULL) return; // ref already GC'd - static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); - static JNF_MEMBER_CACHE(jm_displayReconfiguration, jc_CGraphicsEnvironment, "_displayReconfiguration", "(IZ)V"); - JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, - (jint) display, - (jboolean) flags & kCGDisplayRemoveFlag); - }); + [ThreadUtilities performOnMainThreadWaiting:NO block:^() { + + JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { + JNFWeakJObjectWrapper *wrapper = (JNFWeakJObjectWrapper *)userInfo; + + jobject graphicsEnv = [wrapper jObjectWithEnv:env]; + if (graphicsEnv == NULL) return; // ref already GC'd + static JNF_CLASS_CACHE(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); + static JNF_MEMBER_CACHE(jm_displayReconfiguration, + jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V"); + JNFCallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, + (jint) display, (jboolean) flags & kCGDisplayRemoveFlag); + }); + }]; } /* diff --git a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m index 1ad7d042e6a2297db2f663e6f457032d0a13a7cb..5d5fb8f7ea2e921d7eb0a0c1ce74f8d2bf8d50c4 100644 --- a/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m +++ b/src/macosx/native/sun/java2d/opengl/CGLGraphicsConfig.m @@ -236,6 +236,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo } NSOpenGLPixelFormatAttribute attrs[] = { + NSOpenGLPFAAllowOfflineRenderers, NSOpenGLPFAClosestPolicy, NSOpenGLPFAWindow, NSOpenGLPFAPixelBuffer, diff --git a/src/share/classes/java/awt/Component.java b/src/share/classes/java/awt/Component.java index e826787316f91062b7093c630a7028c3f8b4bbbd..516c6fd0d6c8b3cd4a70eb26dbb1a938f883dd06 100644 --- a/src/share/classes/java/awt/Component.java +++ b/src/share/classes/java/awt/Component.java @@ -312,7 +312,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @see GraphicsConfiguration * @see #getGraphicsConfiguration */ - private transient GraphicsConfiguration graphicsConfig = null; + private transient volatile GraphicsConfiguration graphicsConfig; /** * A reference to a BufferStrategy object @@ -1141,9 +1141,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @since 1.3 */ public GraphicsConfiguration getGraphicsConfiguration() { - synchronized(getTreeLock()) { - return getGraphicsConfiguration_NoClientCode(); - } + return getGraphicsConfiguration_NoClientCode(); } final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() { diff --git a/src/share/classes/java/awt/Window.java b/src/share/classes/java/awt/Window.java index 1052a200c7d7517113f901833cf85655fefdbc68..810168c159259abc02433c1f86b9851534cf82b5 100644 --- a/src/share/classes/java/awt/Window.java +++ b/src/share/classes/java/awt/Window.java @@ -348,7 +348,7 @@ public class Window extends Container implements Accessible { * @see #getOpacity() * @since 1.7 */ - private float opacity = 1.0f; + private volatile float opacity = 1.0f; /** * The shape assigned to this window. This field is set to {@code null} if @@ -1040,9 +1040,7 @@ public class Window extends Container implements Accessible { closeSplashScreen(); Dialog.checkShouldBeBlocked(this); super.show(); - synchronized (getTreeLock()) { - this.locationByPlatform = false; - } + locationByPlatform = false; for (int i = 0; i < ownedWindowList.size(); i++) { Window child = ownedWindowList.elementAt(i).get(); if ((child != null) && child.showWithParent) { @@ -1115,9 +1113,7 @@ public class Window extends Container implements Accessible { modalBlocker.unblockWindow(this); } super.hide(); - synchronized (getTreeLock()) { - this.locationByPlatform = false; - } + locationByPlatform = false; } final void clearMostRecentFocusOwnerOnHide() { @@ -3398,7 +3394,7 @@ public class Window extends Container implements Accessible { return super.canContainFocusOwner(focusOwnerCandidate) && isFocusableWindow(); } - private boolean locationByPlatform = locationByPlatformProp; + private volatile boolean locationByPlatform = locationByPlatformProp; /** @@ -3469,9 +3465,7 @@ public class Window extends Container implements Accessible { * @since 1.5 */ public boolean isLocationByPlatform() { - synchronized (getTreeLock()) { - return locationByPlatform; - } + return locationByPlatform; } /** @@ -3560,9 +3554,7 @@ public class Window extends Container implements Accessible { * @since 1.7 */ public float getOpacity() { - synchronized (getTreeLock()) { - return opacity; - } + return opacity; } /** diff --git a/src/share/classes/sun/swing/CachedPainter.java b/src/share/classes/sun/swing/CachedPainter.java index defc35f25432d94697130a5bcdec36d3c3f4e5ed..e49c60ecd393ce7b4da03928bcbd2d3e8ae7aeee 100644 --- a/src/share/classes/sun/swing/CachedPainter.java +++ b/src/share/classes/sun/swing/CachedPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,9 +53,7 @@ import java.util.*; */ public abstract class CachedPainter { // CacheMap maps from class to ImageCache. - private static final Map cacheMap = - new HashMap(); - + private static final Map cacheMap = new HashMap<>(); private static ImageCache getCache(Object key) { synchronized(CachedPainter.class) { @@ -96,20 +94,8 @@ public abstract class CachedPainter { if (w <= 0 || h <= 0) { return; } - if (c != null) { - synchronized(c.getTreeLock()) { - synchronized(CachedPainter.class) { - // If c is non-null, synchronize on the tree lock. - // This is necessary because asking for the - // GraphicsConfiguration will grab a tree lock. - paint0(c, g, x, y, w, h, args); - } - } - } - else { - synchronized(CachedPainter.class) { - paint0(c, g, x, y, w, h, args); - } + synchronized (CachedPainter.class) { + paint0(c, g, x, y, w, h, args); } } diff --git a/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java b/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java new file mode 100644 index 0000000000000000000000000000000000000000..91e651cebb90b917b28f7d2055705da4f3734234 --- /dev/null +++ b/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.Window; + +import static java.util.concurrent.TimeUnit.MINUTES; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + +/** + * @test + * @bug 8138764 + */ +public final class TreeLockDeadlock extends Frame { + + @Override + public synchronized GraphicsConfiguration getGraphicsConfiguration() { + return super.getGraphicsConfiguration(); + } + + @Override + public synchronized void reshape(int x, int y, int width, int height) { + super.reshape(x, y, width, height); + } + + @Override + public synchronized float getOpacity() { + return super.getOpacity(); + } + + public static void main(final String[] args) throws Exception { + final Window window = new TreeLockDeadlock(); + window.setSize(300, 300); + test(window); + } + + private static void test(final Window window) throws Exception { + final long start = System.nanoTime(); + final long end = start + NANOSECONDS.convert(1, MINUTES); + + final Runnable r1 = () -> { + while (System.nanoTime() < end) { + window.setBounds(window.getBounds()); + } + }; + final Runnable r2 = () -> { + while (System.nanoTime() < end) { + window.getGraphicsConfiguration(); + window.getOpacity(); + } + }; + + final Thread t1 = new Thread(r1); + final Thread t2 = new Thread(r1); + final Thread t3 = new Thread(r2); + final Thread t4 = new Thread(r2); + + t1.start(); + t2.start(); + t3.start(); + t4.start(); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + } +}