--- old/src/java.desktop/share/classes/java/awt/Component.java 2015-10-06 16:41:46.000000000 +0300 +++ new/src/java.desktop/share/classes/java/awt/Component.java 2015-10-06 16:41:46.000000000 +0300 @@ -312,7 +312,7 @@ * @see GraphicsConfiguration * @see #getGraphicsConfiguration */ - private transient GraphicsConfiguration graphicsConfig = null; + private transient volatile GraphicsConfiguration graphicsConfig; /** * A reference to a BufferStrategy object @@ -1143,9 +1143,7 @@ * @since 1.3 */ public GraphicsConfiguration getGraphicsConfiguration() { - synchronized(getTreeLock()) { - return getGraphicsConfiguration_NoClientCode(); - } + return getGraphicsConfiguration_NoClientCode(); } final GraphicsConfiguration getGraphicsConfiguration_NoClientCode() { --- old/src/java.desktop/share/classes/java/awt/Window.java 2015-10-06 16:41:47.000000000 +0300 +++ new/src/java.desktop/share/classes/java/awt/Window.java 2015-10-06 16:41:47.000000000 +0300 @@ -347,7 +347,7 @@ * @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 @@ 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 @@ modalBlocker.unblockWindow(this); } super.hide(); - synchronized (getTreeLock()) { - this.locationByPlatform = false; - } + locationByPlatform = false; } final void clearMostRecentFocusOwnerOnHide() { @@ -3411,7 +3407,7 @@ return super.canContainFocusOwner(focusOwnerCandidate) && isFocusableWindow(); } - private boolean locationByPlatform = locationByPlatformProp; + private volatile boolean locationByPlatform = locationByPlatformProp; /** @@ -3482,9 +3478,7 @@ * @since 1.5 */ public boolean isLocationByPlatform() { - synchronized (getTreeLock()) { - return locationByPlatform; - } + return locationByPlatform; } /** @@ -3573,9 +3567,7 @@ * @since 1.7 */ public float getOpacity() { - synchronized (getTreeLock()) { - return opacity; - } + return opacity; } /** --- old/src/java.desktop/share/classes/sun/swing/CachedPainter.java 2015-10-06 16:41:48.000000000 +0300 +++ new/src/java.desktop/share/classes/sun/swing/CachedPainter.java 2015-10-06 16:41:48.000000000 +0300 @@ -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 @@ */ 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 @@ 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); } } --- /dev/null 2015-10-06 16:41:49.000000000 +0300 +++ new/test/java/awt/Component/TreeLockDeadlock/TreeLockDeadlock.java 2015-10-06 16:41:48.000000000 +0300 @@ -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(); + } +}