diff options
Diffstat (limited to 'java/openjdk6/files/icedtea/openjdk/7064279-resource_release.patch')
-rw-r--r-- | java/openjdk6/files/icedtea/openjdk/7064279-resource_release.patch | 436 |
1 files changed, 436 insertions, 0 deletions
diff --git a/java/openjdk6/files/icedtea/openjdk/7064279-resource_release.patch b/java/openjdk6/files/icedtea/openjdk/7064279-resource_release.patch new file mode 100644 index 000000000000..22d0e2caecd4 --- /dev/null +++ b/java/openjdk6/files/icedtea/openjdk/7064279-resource_release.patch @@ -0,0 +1,436 @@ +# HG changeset patch +# User andrew +# Date 1365712268 -3600 +# Node ID 4d66f7ebcf99c1b322f47ff0aa6adadcd995f8f4 +# Parent df591e0dfd349dc5986cc17949939c588d5a9690 +7064279: Introspector.getBeanInfo() should release some resources in timely manner +Reviewed-by: art, alexp + +diff --git a/src/share/classes/java/beans/Beans.java b/src/share/classes/java/beans/Beans.java +--- jdk/src/share/classes/java/beans/Beans.java ++++ jdk/src/share/classes/java/beans/Beans.java +@@ -32,7 +32,6 @@ + import java.applet.AppletStub; + import java.applet.AudioClip; + +-import java.awt.GraphicsEnvironment; + import java.awt.Image; + + import java.beans.beancontext.BeanContext; +@@ -53,15 +52,11 @@ + import java.util.Iterator; + import java.util.Vector; + +-import sun.awt.AppContext; +- + /** + * This class provides some general purpose beans control methods. + */ + + public class Beans { +- private static final Object DESIGN_TIME = new Object(); +- private static final Object GUI_AVAILABLE = new Object(); + + /** + * <p> +@@ -395,8 +390,7 @@ + * @see DesignMode + */ + public static boolean isDesignTime() { +- Object value = AppContext.getAppContext().get(DESIGN_TIME); +- return (value instanceof Boolean) && (Boolean) value; ++ return ThreadGroupContext.getContext().isDesignTime(); + } + + /** +@@ -413,8 +407,7 @@ + * + */ + public static boolean isGuiAvailable() { +- Object value = AppContext.getAppContext().get(GUI_AVAILABLE); +- return (value instanceof Boolean) ? (Boolean) value : !GraphicsEnvironment.isHeadless(); ++ return ThreadGroupContext.getContext().isGuiAvailable(); + } + + /** +@@ -440,7 +433,7 @@ + if (sm != null) { + sm.checkPropertiesAccess(); + } +- AppContext.getAppContext().put(DESIGN_TIME, Boolean.valueOf(isDesignTime)); ++ ThreadGroupContext.getContext().setDesignTime(isDesignTime); + } + + /** +@@ -466,7 +459,7 @@ + if (sm != null) { + sm.checkPropertiesAccess(); + } +- AppContext.getAppContext().put(GUI_AVAILABLE, Boolean.valueOf(isGuiAvailable)); ++ ThreadGroupContext.getContext().setGuiAvailable(isGuiAvailable); + } + } + +diff --git a/src/share/classes/java/beans/Introspector.java b/src/share/classes/java/beans/Introspector.java +--- jdk/src/share/classes/java/beans/Introspector.java ++++ jdk/src/share/classes/java/beans/Introspector.java +@@ -38,7 +38,6 @@ + import java.util.EventListener; + import java.util.List; + import java.util.TreeMap; +-import sun.awt.AppContext; + import sun.reflect.misc.ReflectUtil; + + /** +@@ -103,10 +102,7 @@ + public final static int IGNORE_ALL_BEANINFO = 3; + + // Static Caches to speed up introspection. +- private static WeakCache<Class<?>, Method[]> declaredMethodCache = +- new WeakCache<Class<?>, Method[]>(); +- +- private static final Object BEANINFO_CACHE = new Object(); ++ private static final WeakCache<Class<?>, Method[]> declaredMethodCache = new WeakCache<>(); + + private Class beanClass; + private BeanInfo explicitBeanInfo; +@@ -170,21 +166,15 @@ + if (!ReflectUtil.isPackageAccessible(beanClass)) { + return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); + } +- WeakCache<Class<?>, BeanInfo> beanInfoCache; ++ ThreadGroupContext context = ThreadGroupContext.getContext(); + BeanInfo beanInfo; +- synchronized (BEANINFO_CACHE) { +- beanInfoCache = (WeakCache<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); +- +- if (beanInfoCache == null) { +- beanInfoCache = new WeakCache<Class<?>, BeanInfo>(); +- AppContext.getAppContext().put(BEANINFO_CACHE, beanInfoCache); +- } +- beanInfo = beanInfoCache.get(beanClass); ++ synchronized (declaredMethodCache) { ++ beanInfo = context.getBeanInfo(beanClass); + } + if (beanInfo == null) { + beanInfo = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); +- synchronized (BEANINFO_CACHE) { +- beanInfoCache.put(beanClass, beanInfo); ++ synchronized (declaredMethodCache) { ++ context.putBeanInfo(beanClass, beanInfo); + } + } + return beanInfo; +@@ -334,11 +324,8 @@ + */ + + public static void flushCaches() { +- synchronized (BEANINFO_CACHE) { +- WeakCache beanInfoCache = (WeakCache) AppContext.getAppContext().get(BEANINFO_CACHE); +- if (beanInfoCache != null) { +- beanInfoCache.clear(); +- } ++ synchronized (declaredMethodCache) { ++ ThreadGroupContext.getContext().clearBeanInfoCache(); + declaredMethodCache.clear(); + } + } +@@ -362,11 +349,8 @@ + if (clz == null) { + throw new NullPointerException(); + } +- synchronized (BEANINFO_CACHE) { +- WeakCache beanInfoCache = (WeakCache) AppContext.getAppContext().get(BEANINFO_CACHE); +- if (beanInfoCache != null) { +- beanInfoCache.put(clz, null); +- } ++ synchronized (declaredMethodCache) { ++ ThreadGroupContext.getContext().removeBeanInfo(clz); + declaredMethodCache.put(clz, null); + } + } +@@ -1313,7 +1297,7 @@ + if (!ReflectUtil.isPackageAccessible(clz)) { + return new Method[0]; + } +- synchronized (BEANINFO_CACHE) { ++ synchronized (declaredMethodCache) { + Method[] result = declaredMethodCache.get(clz); + if (result == null) { + result = clz.getMethods(); +diff --git a/src/share/classes/java/beans/ThreadGroupContext.java b/src/share/classes/java/beans/ThreadGroupContext.java +new file mode 100644 +--- /dev/null ++++ jdk/src/share/classes/java/beans/ThreadGroupContext.java +@@ -0,0 +1,133 @@ ++/* ++ * Copyright (c) 2011, 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. 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. ++ */ ++ ++package java.beans; ++ ++import com.sun.beans.finder.BeanInfoFinder; ++import com.sun.beans.finder.PropertyEditorFinder; ++ ++import java.awt.GraphicsEnvironment; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.WeakHashMap; ++ ++/** ++ * The {@code ThreadGroupContext} is an application-dependent ++ * context referenced by the specific {@link ThreadGroup}. ++ * This is a replacement for the {@link sun.awt.AppContext}. ++ * ++ * @author Sergey Malenkov ++ */ ++final class ThreadGroupContext { ++ ++ private static final Map<ThreadGroup, ThreadGroupContext> contexts = new WeakHashMap<>(); ++ ++ /** ++ * Returns the appropriate {@code AppContext} for the caller, ++ * as determined by its {@code ThreadGroup}. ++ * ++ * @return the application-dependent context ++ */ ++ static ThreadGroupContext getContext() { ++ ThreadGroup group = Thread.currentThread().getThreadGroup(); ++ synchronized (contexts) { ++ ThreadGroupContext context = contexts.get(group); ++ if (context == null) { ++ context = new ThreadGroupContext(); ++ contexts.put(group, context); ++ } ++ return context; ++ } ++ } ++ ++ private volatile boolean isDesignTime; ++ private volatile Boolean isGuiAvailable; ++ ++ private Map<Class<?>, BeanInfo> beanInfoCache; ++ private BeanInfoFinder beanInfoFinder; ++ private PropertyEditorFinder propertyEditorFinder; ++ ++ ++ boolean isDesignTime() { ++ return this.isDesignTime; ++ } ++ ++ void setDesignTime(boolean isDesignTime) { ++ this.isDesignTime = isDesignTime; ++ } ++ ++ ++ boolean isGuiAvailable() { ++ Boolean isGuiAvailable = this.isGuiAvailable; ++ return (isGuiAvailable != null) ++ ? isGuiAvailable.booleanValue() ++ : !GraphicsEnvironment.isHeadless(); ++ } ++ ++ void setGuiAvailable(boolean isGuiAvailable) { ++ this.isGuiAvailable = Boolean.valueOf(isGuiAvailable); ++ } ++ ++ ++ BeanInfo getBeanInfo(Class<?> type) { ++ return (this.beanInfoCache != null) ++ ? this.beanInfoCache.get(type) ++ : null; ++ } ++ ++ BeanInfo putBeanInfo(Class<?> type, BeanInfo info) { ++ if (this.beanInfoCache == null) { ++ this.beanInfoCache = new WeakHashMap<>(); ++ } ++ return this.beanInfoCache.put(type, info); ++ } ++ ++ void removeBeanInfo(Class<?> type) { ++ if (this.beanInfoCache != null) { ++ this.beanInfoCache.remove(type); ++ } ++ } ++ ++ void clearBeanInfoCache() { ++ if (this.beanInfoCache != null) { ++ this.beanInfoCache.clear(); ++ } ++ } ++ ++ ++ synchronized BeanInfoFinder getBeanInfoFinder() { ++ if (this.beanInfoFinder == null) { ++ this.beanInfoFinder = new BeanInfoFinder(); ++ } ++ return this.beanInfoFinder; ++ } ++ ++ synchronized PropertyEditorFinder getPropertyEditorFinder() { ++ if (this.propertyEditorFinder == null) { ++ this.propertyEditorFinder = new PropertyEditorFinder(); ++ } ++ return this.propertyEditorFinder; ++ } ++} +diff --git a/test/java/beans/Beans/6669869/TestDesignTime.java b/test/java/beans/Beans/6669869/TestDesignTime.java +--- jdk/test/java/beans/Beans/6669869/TestDesignTime.java ++++ jdk/test/java/beans/Beans/6669869/TestDesignTime.java +@@ -29,7 +29,6 @@ + */ + + import java.beans.Beans; +-import sun.awt.SunToolkit; + + public class TestDesignTime implements Runnable { + public static void main(String[] args) throws InterruptedException { +@@ -44,7 +43,6 @@ + } + + public void run() { +- SunToolkit.createNewAppContext(); + if (Beans.isDesignTime()) { + throw new Error("shared DesignTime property"); + } +diff --git a/test/java/beans/Beans/6669869/TestGuiAvailable.java b/test/java/beans/Beans/6669869/TestGuiAvailable.java +--- jdk/test/java/beans/Beans/6669869/TestGuiAvailable.java ++++ jdk/test/java/beans/Beans/6669869/TestGuiAvailable.java +@@ -30,7 +30,6 @@ + + import java.awt.GraphicsEnvironment; + import java.beans.Beans; +-import sun.awt.SunToolkit; + + public class TestGuiAvailable implements Runnable { + public static void main(String[] args) throws InterruptedException { +@@ -45,7 +44,6 @@ + } + + public void run() { +- SunToolkit.createNewAppContext(); + if (Beans.isGuiAvailable() == GraphicsEnvironment.isHeadless()) { + throw new Error("shared GuiAvailable property"); + } +diff --git a/test/java/beans/Introspector/7064279/Test7064279.java b/test/java/beans/Introspector/7064279/Test7064279.java +new file mode 100644 +--- /dev/null ++++ jdk/test/java/beans/Introspector/7064279/Test7064279.java +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (c) 2011, 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. ++ */ ++ ++/* ++ * @test ++ * @bug 7064279 ++ * @summary Tests that Introspector does not have strong references to context class loader ++ * @author Sergey Malenkov ++ */ ++ ++import java.beans.Introspector; ++import java.io.File; ++import java.lang.ref.WeakReference; ++import java.net.URL; ++import java.net.URLClassLoader; ++ ++public class Test7064279 { ++ ++ public static void main(String[] args) throws Exception { ++ WeakReference ref = new WeakReference(test("test.jar", "test.Test")); ++ try { ++ int[] array = new int[1024]; ++ while (true) { ++ array = new int[array.length << 1]; ++ } ++ } ++ catch (OutOfMemoryError error) { ++ System.gc(); ++ } ++ if (null != ref.get()) { ++ throw new Error("ClassLoader is not released"); ++ } ++ } ++ ++ private static Object test(String jarName, String className) throws Exception { ++ StringBuilder sb = new StringBuilder(256); ++ sb.append("file:"); ++ sb.append(System.getProperty("test.src", ".")); ++ sb.append(File.separatorChar); ++ sb.append(jarName); ++ ++ ClassLoader newLoader = new URLClassLoader(new URL[] { new URL(sb.toString()) }); ++ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); ++ ++ Thread.currentThread().setContextClassLoader(newLoader); ++ test(newLoader.loadClass(className)); ++ Thread.currentThread().setContextClassLoader(oldLoader); ++ ++ return newLoader; ++ } ++ ++ private static void test(Class type) throws Exception { ++ Introspector.getBeanInfo(type); ++ } ++} +diff --git a/test/java/beans/Introspector/Test6660539.java b/test/java/beans/Introspector/Test6660539.java +--- jdk/test/java/beans/Introspector/Test6660539.java ++++ jdk/test/java/beans/Introspector/Test6660539.java +@@ -28,8 +28,6 @@ + * @author Sergey Malenkov + */ + +-import sun.awt.SunToolkit; +- + import java.beans.BeanInfo; + import java.beans.IntrospectionException; + import java.beans.Introspector; +@@ -49,7 +47,6 @@ + } + + public void run() { +- SunToolkit.createNewAppContext(); + for (PropertyDescriptor pd : getPropertyDescriptors()) { + if (pd.getDisplayName().equals(NAME)) + throw new Error("shared BeanInfo cache"); |