# HG changeset patch # User lana # Date 1271807242 25200 # Node ID 3c1c9fda17a19d064d9915edf112a3eabd3e313a # Parent 1d1927f9ec097b62c913921e2dfa5dbaf5dc325b# Parent fa9f5ce2006edfb06131601b671d3eb82dff9fbd Merge diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/share/classes/sun/font/SunFontManager.java --- a/jdk/src/share/classes/sun/font/SunFontManager.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/share/classes/sun/font/SunFontManager.java Tue Apr 20 16:47:22 2010 -0700 @@ -2310,6 +2310,7 @@ tgn != null; tg = tgn, tgn = tg.getParent()); fileCloser = new Thread(tg, fileCloserRunnable); + fileCloser.setContextClassLoader(null); Runtime.getRuntime().addShutdownHook(fileCloser); return null; } diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/share/classes/sun/java2d/Disposer.java --- a/jdk/src/share/classes/sun/java2d/Disposer.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/share/classes/sun/java2d/Disposer.java Tue Apr 20 16:47:22 2010 -0700 @@ -84,6 +84,7 @@ tg = tgn, tgn = tg.getParent()); Thread t = new Thread(tg, disposerInstance, "Java2D Disposer"); + t.setContextClassLoader(null); t.setDaemon(true); t.setPriority(Thread.MAX_PRIORITY); t.start(); diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/share/classes/sun/java2d/loops/GraphicsPrimitive.java --- a/jdk/src/share/classes/sun/java2d/loops/GraphicsPrimitive.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/share/classes/sun/java2d/loops/GraphicsPrimitive.java Tue Apr 20 16:47:22 2010 -0700 @@ -417,7 +417,9 @@ public static void setShutdownHook() { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { - Runtime.getRuntime().addShutdownHook(new TraceReporter()); + TraceReporter t = new TraceReporter(); + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); return null; } }); diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/solaris/classes/sun/awt/X11/XToolkit.java --- a/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Apr 20 16:47:22 2010 -0700 @@ -307,22 +307,35 @@ } finally { awtUnlock(); } - - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); - if (peer != null) { - peer.dispose(); + PrivilegedAction a = new PrivilegedAction() { + public Void run() { + ThreadGroup mainTG = Thread.currentThread().getThreadGroup(); + ThreadGroup parentTG = mainTG.getParent(); + while (parentTG != null) { + mainTG = parentTG; + parentTG = mainTG.getParent(); } - if (xs != null) { - ((XAWTXSettings)xs).dispose(); - } - freeXKB(); - if (log.isLoggable(PlatformLogger.FINE)) { - dumpPeers(); - } + Thread shutdownThread = new Thread(mainTG, "XToolkt-Shutdown-Thread") { + public void run() { + XSystemTrayPeer peer = XSystemTrayPeer.getPeerInstance(); + if (peer != null) { + peer.dispose(); + } + if (xs != null) { + ((XAWTXSettings)xs).dispose(); + } + freeXKB(); + if (log.isLoggable(PlatformLogger.FINE)) { + dumpPeers(); + } + } + }; + shutdownThread.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(shutdownThread); + return null; } - }); + }; + AccessController.doPrivileged(a); } static String getCorrectXIDString(String val) { diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java --- a/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java Tue Apr 20 16:47:22 2010 -0700 @@ -32,6 +32,8 @@ import java.awt.GraphicsConfiguration; import java.awt.Rectangle; import java.awt.Window; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashSet; import java.util.HashMap; @@ -402,17 +404,30 @@ // is already in the original DisplayMode at that time, this // hook will have no effect) shutdownHookRegistered = true; - Runnable r = new Runnable() { - public void run() { - Window old = getFullScreenWindow(); - if (old != null) { - exitFullScreenExclusive(old); - setDisplayMode(origDisplayMode); + PrivilegedAction a = new PrivilegedAction() { + public Void run() { + ThreadGroup mainTG = Thread.currentThread().getThreadGroup(); + ThreadGroup parentTG = mainTG.getParent(); + while (parentTG != null) { + mainTG = parentTG; + parentTG = mainTG.getParent(); } + Runnable r = new Runnable() { + public void run() { + Window old = getFullScreenWindow(); + if (old != null) { + exitFullScreenExclusive(old); + setDisplayMode(origDisplayMode); + } + } + }; + Thread t = new Thread(mainTG, r,"Display-Change-Shutdown-Thread-"+screen); + t.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(t); + return null; } }; - Thread t = new Thread(r,"Display-Change-Shutdown-Thread-"+screen); - Runtime.getRuntime().addShutdownHook(t); + AccessController.doPrivileged(a); } // switch to the new DisplayMode diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/solaris/classes/sun/awt/motif/MToolkit.java --- a/jdk/src/solaris/classes/sun/awt/motif/MToolkit.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/solaris/classes/sun/awt/motif/MToolkit.java Tue Apr 20 16:47:22 2010 -0700 @@ -156,27 +156,27 @@ Thread toolkitThread = new Thread(this, "AWT-Motif"); toolkitThread.setPriority(Thread.NORM_PRIORITY + 1); toolkitThread.setDaemon(true); - ThreadGroup mainTG = (ThreadGroup)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - ThreadGroup currentTG = - Thread.currentThread().getThreadGroup(); - ThreadGroup parentTG = currentTG.getParent(); - while (parentTG != null) { - currentTG = parentTG; - parentTG = currentTG.getParent(); - } - return currentTG; + + PrivilegedAction a = new PrivilegedAction() { + public Void run() { + ThreadGroup mainTG = Thread.currentThread().getThreadGroup(); + ThreadGroup parentTG = mainTG.getParent(); + + while (parentTG != null) { + mainTG = parentTG; + parentTG = mainTG.getParent(); } - }); - - Runtime.getRuntime().addShutdownHook( - new Thread(mainTG, new Runnable() { - public void run() { - shutdown(); - } - }, "Shutdown-Thread") - ); + Thread shutdownThread = new Thread(mainTG, new Runnable() { + public void run() { + shutdown(); + } + }, "Shutdown-Thread"); + shutdownThread.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(shutdownThread); + return null; + } + }; + AccessController.doPrivileged(a); /* * Fix for 4701990. diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/windows/classes/sun/awt/windows/WToolkit.java --- a/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/windows/classes/sun/awt/windows/WToolkit.java Tue Apr 20 16:47:22 2010 -0700 @@ -266,27 +266,25 @@ boolean startPump = init(); if (startPump) { - ThreadGroup mainTG = (ThreadGroup)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - ThreadGroup currentTG = - Thread.currentThread().getThreadGroup(); - ThreadGroup parentTG = currentTG.getParent(); - while (parentTG != null) { - currentTG = parentTG; - parentTG = currentTG.getParent(); - } - return currentTG; + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + ThreadGroup currentTG = + Thread.currentThread().getThreadGroup(); + ThreadGroup parentTG = currentTG.getParent(); + while (parentTG != null) { + currentTG = parentTG; + parentTG = currentTG.getParent(); } + Thread shutdown = new Thread(currentTG, new Runnable() { + public void run() { + shutdown(); + } + }); + shutdown.setContextClassLoader(null); + Runtime.getRuntime().addShutdownHook(shutdown); + return null; + } }); - - Runtime.getRuntime().addShutdownHook( - new Thread(mainTG, new Runnable() { - public void run() { - shutdown(); - } - }) - ); } synchronized(this) { diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java --- a/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Wed Jul 05 17:10:17 2017 +0200 +++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DScreenUpdateManager.java Tue Apr 20 16:47:22 2010 -0700 @@ -101,17 +101,15 @@ currentTG = parentTG; parentTG = currentTG.getParent(); } + Thread shutdown = new Thread(currentTG, new Runnable() { + public void run() { + done = true; + wakeUpUpdateThread(); + } + }); + shutdown.setContextClassLoader(null); try { - Runtime.getRuntime().addShutdownHook( - new Thread(currentTG, - new Runnable() { - public void run() { - done = true; - wakeUpUpdateThread(); - } - } - ) - ); + Runtime.getRuntime().addShutdownHook(shutdown); } catch (Exception e) { done = true; } diff -r 1d1927f9ec09 -r 3c1c9fda17a1 jdk/test/sun/awt/font/ClassLoaderLeakTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/awt/font/ClassLoaderLeakTest.java Tue Apr 20 16:47:22 2010 -0700 @@ -0,0 +1,220 @@ +/* + * Copyright 2010 Sun Microsystems, 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. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/** + * @test + * @bug 6936389 + * + * @summary Test verifes that LogManager shutdown hook does not cause + * an application classloader leaks. + * + * @run main/othervm ClassLoaderLeakTest FontManagerTest + */ + +import java.awt.Font; +import java.awt.Graphics; +import java.io.File; +import java.lang.ref.WeakReference; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.concurrent.CountDownLatch; + +public class ClassLoaderLeakTest { + + private static CountDownLatch doneSignal; + private static CountDownLatch launchSignal; + private static Throwable launchFailure = null; + + public static void main(String[] args) { + doneSignal = new CountDownLatch(1); + launchSignal = new CountDownLatch(1); + + String testcase = "FontManagerTest"; + + if (args.length > 0) { + testcase = args[0]; + } + + /* prepare test class loader */ + URL pwd = null; + try { + + pwd = new File(System.getProperty("test.classes", ".")).toURL(); + } catch (MalformedURLException e) { + throw new RuntimeException("Test failed.", e); + } + System.out.println("PWD: " + pwd); + URL[] urls = new URL[]{pwd}; + + MyClassLoader appClassLoader = new MyClassLoader(urls, "test0"); + WeakReference ref = + new WeakReference(appClassLoader); + + ThreadGroup appsThreadGroup = new ThreadGroup("MyAppsThreadGroup"); + + Runnable launcher = new TestLauncher(testcase); + + Thread appThread = new Thread(appsThreadGroup, launcher, "AppThread-0"); + appThread.setContextClassLoader(appClassLoader); + + appThread.start(); + appsThreadGroup = null; + appClassLoader = null; + launcher = null; + appThread = null; + + /* wait for laucnh completion */ + try { + launchSignal.await(); + } catch (InterruptedException e) { + } + + /* check if launch failed */ + if (launchFailure != null) { + throw new RuntimeException("Test failed.", launchFailure); + } + + /* wait for test app excution completion */ + try { + doneSignal.await(); + } catch (InterruptedException e) { + } + + /* give a chance to GC */ + waitAndGC(9); + + if (ref.get() != null) { + throw new RuntimeException("Test failed: classloader is still alive"); + } + + + System.out.println("Test passed."); + } + + private static class TestLauncher implements Runnable { + + private String className; + + public TestLauncher(String name) { + className = name; + } + + public void run() { + try { + ClassLoader cl = + Thread.currentThread().getContextClassLoader(); + Class appMain = cl.loadClass(className); + Method launch = + appMain.getMethod("launch", doneSignal.getClass()); + + Constructor c = appMain.getConstructor(); + + Object o = c.newInstance(); + + launch.invoke(o, doneSignal); + + } catch (Throwable e) { + launchFailure = e; + } finally { + launchSignal.countDown(); + } + } + } + + private static class MyClassLoader extends URLClassLoader { + + private static boolean verbose = + Boolean.getBoolean("verboseClassLoading"); + private String uniqClassName; + + public MyClassLoader(URL[] urls, String uniq) { + super(urls); + + uniqClassName = uniq; + } + + public Class loadClass(String name) throws ClassNotFoundException { + if (verbose) { + System.out.printf("%s: load class %s\n", uniqClassName, name); + } + if (uniqClassName.equals(name)) { + return Object.class; + } + return super.loadClass(name); + } + + public String toString() { + return "MyClassLoader(" + uniqClassName + ")"; + } + } + + private static void waitAndGC(int sec) { + int cnt = sec; + System.out.print("Wait "); + while (cnt-- > 0) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + // do GC every 3 seconds + if (cnt % 3 == 2) { + System.gc(); + System.out.print("+"); + } else { + System.out.print("."); + } + //checkErrors(); + } + System.out.println(""); + } +} + +abstract class AppTest { + + public AppTest() { + } + + protected abstract void doTest(); + + public void launch(CountDownLatch done) { + System.out.println("Testcase: " + this.getClass().getName()); + try { + doTest(); + } finally { + done.countDown(); + } + } +} + +class FontManagerTest extends AppTest { + + public FontManagerTest() { + } + + protected void doTest() { + Font f = new Font(Font.SANS_SERIF, Font.ITALIC, 24); + f.getNumGlyphs(); + } +}