6995195: Static initialization deadlock in sun.java2d.loops.Blit and GraphicsPrimitiveMgr
Reviewed-by: serb, aivanov
This commit is contained in:
parent
748476fd80
commit
de0c05da07
src/java.desktop/share/classes/sun/java2d/loops
Blit.javaBlitBg.javaDrawGlyphList.javaDrawGlyphListAA.javaDrawGlyphListColor.javaFillRect.javaGraphicsPrimitiveMgr.javaMaskBlit.javaMaskFill.java
test/jdk/sun/java2d/loops
@ -36,6 +36,7 @@ import java.lang.ref.WeakReference;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.pipe.SpanIterator;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* Blit
|
||||
@ -111,7 +112,7 @@ public class Blit extends GraphicsPrimitive
|
||||
int width, int height);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new Blit(null, null, null));
|
||||
GeneralPrimitives.register(new Blit(null, null, null));
|
||||
}
|
||||
|
||||
protected GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
|
@ -37,6 +37,7 @@ import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* BlitBg
|
||||
@ -114,7 +115,7 @@ public class BlitBg extends GraphicsPrimitive
|
||||
int width, int height);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new BlitBg(null, null, null));
|
||||
GeneralPrimitives.register(new BlitBg(null, null, null));
|
||||
}
|
||||
|
||||
protected GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
|
@ -29,6 +29,7 @@ import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* DrawGlyphList - loops for SolidTextRenderer pipe.
|
||||
@ -73,7 +74,7 @@ public class DrawGlyphList extends GraphicsPrimitive {
|
||||
|
||||
// This instance is used only for lookup.
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(
|
||||
GeneralPrimitives.register(
|
||||
new DrawGlyphList(null, null, null));
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* DrawGlyphListAA - loops for AATextRenderer pipe
|
||||
@ -71,7 +72,7 @@ public class DrawGlyphListAA extends GraphicsPrimitive {
|
||||
int fromGlyph, int toGlyph);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(
|
||||
GeneralPrimitives.register(
|
||||
new DrawGlyphListAA(null, null, null));
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ import sun.font.GlyphList;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@ -67,7 +68,7 @@ public class DrawGlyphListColor extends GraphicsPrimitive {
|
||||
|
||||
// This instance is used only for lookup.
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(
|
||||
GeneralPrimitives.register(
|
||||
new DrawGlyphListColor(null, null, null));
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ package sun.java2d.loops;
|
||||
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* FillRect
|
||||
@ -75,7 +76,7 @@ public class FillRect extends GraphicsPrimitive
|
||||
int x, int y, int w, int h);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new FillRect(null, null, null));
|
||||
GeneralPrimitives.register(new FillRect(null, null, null));
|
||||
}
|
||||
|
||||
protected GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
|
@ -42,7 +42,6 @@ public final class GraphicsPrimitiveMgr {
|
||||
|
||||
private static final boolean debugTrace = false;
|
||||
private static GraphicsPrimitive[] primitives;
|
||||
private static GraphicsPrimitive[] generalPrimitives;
|
||||
private static boolean needssort = true;
|
||||
|
||||
private static native void initIDs(Class<?> GP, Class<?> ST, Class<?> CT,
|
||||
@ -121,24 +120,6 @@ public final class GraphicsPrimitiveMgr {
|
||||
primitives = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the general loop which will be used to produce specific
|
||||
* primitives by the {@link GraphicsPrimitive#makePrimitive} function.
|
||||
*
|
||||
* @param gen the graphics primitive to be registered as the general loop
|
||||
*/
|
||||
public static synchronized void registerGeneral(GraphicsPrimitive gen) {
|
||||
if (generalPrimitives == null) {
|
||||
generalPrimitives = new GraphicsPrimitive[] {gen};
|
||||
return;
|
||||
}
|
||||
int len = generalPrimitives.length;
|
||||
GraphicsPrimitive[] newGen = new GraphicsPrimitive[len + 1];
|
||||
System.arraycopy(generalPrimitives, 0, newGen, 0, len);
|
||||
newGen[len] = gen;
|
||||
generalPrimitives = newGen;
|
||||
}
|
||||
|
||||
public static synchronized GraphicsPrimitive locate(int primTypeID,
|
||||
SurfaceType dsttype)
|
||||
{
|
||||
@ -165,7 +146,7 @@ public final class GraphicsPrimitiveMgr {
|
||||
|
||||
if (prim == null) {
|
||||
//System.out.println("Trying general loop");
|
||||
prim = locateGeneral(primTypeID);
|
||||
prim = GeneralPrimitives.locate(primTypeID);
|
||||
if (prim != null) {
|
||||
prim = prim.makePrimitive(srctype, comptype, dsttype);
|
||||
if (prim != null && GraphicsPrimitive.traceflags != 0) {
|
||||
@ -218,20 +199,6 @@ public final class GraphicsPrimitiveMgr {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static GraphicsPrimitive locateGeneral(int primTypeID) {
|
||||
if (generalPrimitives == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < generalPrimitives.length; i++) {
|
||||
GraphicsPrimitive prim = generalPrimitives[i];
|
||||
if (prim.getPrimTypeID() == primTypeID) {
|
||||
return prim;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
//throw new InternalError("No general handler registered for"+signature);
|
||||
}
|
||||
|
||||
private static GraphicsPrimitive locate(PrimitiveSpec spec) {
|
||||
if (needssort) {
|
||||
if (GraphicsPrimitive.traceflags != 0) {
|
||||
@ -274,6 +241,46 @@ public final class GraphicsPrimitiveMgr {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A holder for general primitives to avoid circular dependencies
|
||||
* between GraphicsPrimitiveMgr and Blit/etc classes.
|
||||
*/
|
||||
final static class GeneralPrimitives {
|
||||
|
||||
private static GraphicsPrimitive[] primitives;
|
||||
|
||||
/**
|
||||
* Registers the general loop which will be used to produce specific
|
||||
* primitives by the {@link GraphicsPrimitive#makePrimitive} function.
|
||||
*
|
||||
* @param gen the graphics primitive to be registered as the general loop
|
||||
*/
|
||||
static synchronized void register(GraphicsPrimitive gen) {
|
||||
if (primitives == null) {
|
||||
primitives = new GraphicsPrimitive[]{gen};
|
||||
return;
|
||||
}
|
||||
int len = primitives.length;
|
||||
GraphicsPrimitive[] newGen = new GraphicsPrimitive[len + 1];
|
||||
System.arraycopy(primitives, 0, newGen, 0, len);
|
||||
newGen[len] = gen;
|
||||
primitives = newGen;
|
||||
}
|
||||
|
||||
static synchronized GraphicsPrimitive locate(int primTypeID) {
|
||||
if (primitives == null) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < primitives.length; i++) {
|
||||
GraphicsPrimitive prim = primitives[i];
|
||||
if (prim.getPrimTypeID() == primTypeID) {
|
||||
return prim;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that all of the GraphicsPrimitiveProxy objects actually
|
||||
* resolve to something. Throws a RuntimeException if anything
|
||||
|
@ -30,6 +30,7 @@ import java.lang.ref.WeakReference;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* MaskBlit
|
||||
@ -109,7 +110,7 @@ public class MaskBlit extends GraphicsPrimitive
|
||||
byte[] mask, int maskoff, int maskscan);
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new MaskBlit(null, null, null));
|
||||
GeneralPrimitives.register(new MaskBlit(null, null, null));
|
||||
}
|
||||
|
||||
protected GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
|
@ -32,6 +32,7 @@ import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.java2d.loops.GraphicsPrimitiveMgr.GeneralPrimitives;
|
||||
|
||||
/**
|
||||
* MaskFill
|
||||
@ -141,7 +142,7 @@ public class MaskFill extends GraphicsPrimitive
|
||||
}
|
||||
|
||||
static {
|
||||
GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null));
|
||||
GeneralPrimitives.register(new MaskFill(null, null, null));
|
||||
}
|
||||
|
||||
protected GraphicsPrimitive makePrimitive(SurfaceType srctype,
|
||||
|
70
test/jdk/sun/java2d/loops/GraphicsPrimitiveMgrTest.java
Normal file
70
test/jdk/sun/java2d/loops/GraphicsPrimitiveMgrTest.java
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Azul Systems, Inc. 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.util.concurrent.CountDownLatch;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6995195
|
||||
* @summary Verify that concurrent classloading of GraphicsPrimitiveMgr
|
||||
* and Blit doesn't deadlock
|
||||
* @run main/othervm/timeout=20 GraphicsPrimitiveMgrTest
|
||||
*/
|
||||
public class GraphicsPrimitiveMgrTest {
|
||||
|
||||
private static volatile CountDownLatch latch;
|
||||
|
||||
private static final String C1 = "sun.java2d.loops.GraphicsPrimitiveMgr";
|
||||
private static final String C2 = "sun.java2d.loops.Blit";
|
||||
|
||||
public static void main(final String[] args)
|
||||
throws ClassNotFoundException, InterruptedException
|
||||
{
|
||||
// force loading awt library
|
||||
Class.forName("java.awt.Toolkit");
|
||||
|
||||
latch = new CountDownLatch(2);
|
||||
|
||||
Thread t1 = new Thread(() -> loadClass(C1));
|
||||
Thread t2 = new Thread(() -> loadClass(C2));
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
|
||||
t1.join();
|
||||
t2.join();
|
||||
}
|
||||
|
||||
private static void loadClass(String className) {
|
||||
System.out.println(Thread.currentThread().getName() + " loading " + className);
|
||||
try {
|
||||
latch.countDown();
|
||||
latch.await();
|
||||
Class.forName(className);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user