diff options
Diffstat (limited to 'java/openjdk6/files/icedtea/openjdk/5102804-memory_leak.patch')
-rw-r--r-- | java/openjdk6/files/icedtea/openjdk/5102804-memory_leak.patch | 429 |
1 files changed, 0 insertions, 429 deletions
diff --git a/java/openjdk6/files/icedtea/openjdk/5102804-memory_leak.patch b/java/openjdk6/files/icedtea/openjdk/5102804-memory_leak.patch deleted file mode 100644 index 01dd35c1bee2..000000000000 --- a/java/openjdk6/files/icedtea/openjdk/5102804-memory_leak.patch +++ /dev/null @@ -1,429 +0,0 @@ -# HG changeset patch -# User andrew -# Date 1365704033 -3600 -# Node ID 06255d9f82761abc74c30f31fda00968ffef4bc3 -# Parent a939f541de9af5ccb78225c27cd46cd7dc6bcf87 -5102804: Memory leak in Introspector.getBeanInfo(Class) for custom BeanInfo: Class param (includes WeakCache from 6397609) -Reviewed-by: peterz - -diff --git a/src/share/classes/com/sun/beans/WeakCache.java b/src/share/classes/com/sun/beans/WeakCache.java -new file mode 100644 ---- /dev/null -+++ jdk/src/share/classes/com/sun/beans/WeakCache.java -@@ -0,0 +1,91 @@ -+/* -+ * Copyright 2008 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. Sun designates this -+ * particular file as subject to the "Classpath" exception as provided -+ * by Sun 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 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. -+ */ -+package com.sun.beans; -+ -+import java.lang.ref.Reference; -+import java.lang.ref.WeakReference; -+ -+import java.util.Map; -+import java.util.WeakHashMap; -+ -+/** -+ * A hashtable-based cache with weak keys and weak values. -+ * An entry in the map will be automatically removed -+ * when its key is no longer in the ordinary use. -+ * A value will be automatically removed as well -+ * when it is no longer in the ordinary use. -+ * -+ * @since 1.7 -+ * -+ * @author Sergey A. Malenkov -+ */ -+public final class WeakCache<K, V> { -+ private final Map<K, Reference<V>> map = new WeakHashMap<K, Reference<V>>(); -+ -+ /** -+ * Returns a value to which the specified {@code key} is mapped, -+ * or {@code null} if this map contains no mapping for the {@code key}. -+ * -+ * @param key the key whose associated value is returned -+ * @return a value to which the specified {@code key} is mapped -+ */ -+ public V get(K key) { -+ Reference<V> reference = this.map.get(key); -+ if (reference == null) { -+ return null; -+ } -+ V value = reference.get(); -+ if (value == null) { -+ this.map.remove(key); -+ } -+ return value; -+ } -+ -+ /** -+ * Associates the specified {@code value} with the specified {@code key}. -+ * Removes the mapping for the specified {@code key} from this cache -+ * if it is present and the specified {@code value} is {@code null}. -+ * If the cache previously contained a mapping for the {@code key}, -+ * the old value is replaced by the specified {@code value}. -+ * -+ * @param key the key with which the specified value is associated -+ * @param value the value to be associated with the specified key -+ */ -+ public void put(K key, V value) { -+ if (value != null) { -+ this.map.put(key, new WeakReference<V>(value)); -+ } -+ else { -+ this.map.remove(key); -+ } -+ } -+ -+ /** -+ * Removes all of the mappings from this cache. -+ */ -+ public void clear() { -+ this.map.clear(); -+ } -+} -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 -@@ -25,25 +25,18 @@ - - package java.beans; - -+import com.sun.beans.WeakCache; - import com.sun.beans.finder.ClassFinder; - --import java.lang.ref.Reference; --import java.lang.ref.SoftReference; -- - import java.lang.reflect.Method; - import java.lang.reflect.Modifier; - --import java.security.AccessController; --import java.security.PrivilegedAction; -- --import java.util.Collections; - import java.util.Map; - import java.util.ArrayList; - import java.util.HashMap; - import java.util.Iterator; - import java.util.EventListener; - import java.util.List; --import java.util.WeakHashMap; - import java.util.TreeMap; - import sun.awt.AppContext; - import sun.reflect.misc.ReflectUtil; -@@ -110,8 +103,8 @@ - public final static int IGNORE_ALL_BEANINFO = 3; - - // Static Caches to speed up introspection. -- private static Map declaredMethodCache = -- Collections.synchronizedMap(new WeakHashMap()); -+ private static WeakCache<Class<?>, Method[]> declaredMethodCache = -+ new WeakCache<Class<?>, Method[]>(); - - private static final Object BEANINFO_CACHE = new Object(); - -@@ -177,20 +170,21 @@ - if (!ReflectUtil.isPackageAccessible(beanClass)) { - return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); - } -- Map<Class<?>, BeanInfo> map; - synchronized (BEANINFO_CACHE) { -- map = (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); -- if (map == null) { -- map = Collections.synchronizedMap(new WeakHashMap<Class<?>, BeanInfo>()); -- AppContext.getAppContext().put(BEANINFO_CACHE, map); -+ WeakCache<Class<?>, BeanInfo> beanInfoCache = -+ (WeakCache<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); -+ -+ if (beanInfoCache == null) { -+ beanInfoCache = new WeakCache<Class<?>, BeanInfo>(); -+ AppContext.getAppContext().put(BEANINFO_CACHE, beanInfoCache); - } -+ BeanInfo beanInfo = beanInfoCache.get(beanClass); -+ if (beanInfo == null) { -+ beanInfo = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); -+ beanInfoCache.put(beanClass, beanInfo); -+ } -+ return beanInfo; - } -- BeanInfo bi = map.get(beanClass); -- if (bi == null) { -- bi = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); -- map.put(beanClass, bi); -- } -- return bi; - } - - /** -@@ -337,11 +331,13 @@ - */ - - public static void flushCaches() { -- Map map = (Map) AppContext.getAppContext().get(BEANINFO_CACHE); -- if (map != null) { -- map.clear(); -+ synchronized (BEANINFO_CACHE) { -+ WeakCache beanInfoCache = (WeakCache) AppContext.getAppContext().get(BEANINFO_CACHE); -+ if (beanInfoCache != null) { -+ beanInfoCache.clear(); -+ } -+ declaredMethodCache.clear(); - } -- declaredMethodCache.clear(); - } - - /** -@@ -363,11 +359,13 @@ - if (clz == null) { - throw new NullPointerException(); - } -- Map map = (Map) AppContext.getAppContext().get(BEANINFO_CACHE); -- if (map != null) { -- map.remove(clz); -+ synchronized (BEANINFO_CACHE) { -+ WeakCache beanInfoCache = (WeakCache) AppContext.getAppContext().get(BEANINFO_CACHE); -+ if (beanInfoCache != null) { -+ beanInfoCache.put(clz, null); -+ } -+ declaredMethodCache.put(clz, null); - } -- declaredMethodCache.remove(clz); - } - - //====================================================================== -@@ -1306,41 +1304,26 @@ - /* - * Internal method to return *public* methods within a class. - */ -- private static synchronized Method[] getPublicDeclaredMethods(Class clz) { -+ private static Method[] getPublicDeclaredMethods(Class clz) { - // Looking up Class.getDeclaredMethods is relatively expensive, - // so we cache the results. -- Method[] result = null; - if (!ReflectUtil.isPackageAccessible(clz)) { - return new Method[0]; - } -- final Class fclz = clz; -- Reference ref = (Reference)declaredMethodCache.get(fclz); -- if (ref != null) { -- result = (Method[])ref.get(); -- if (result != null) { -- return result; -+ synchronized (BEANINFO_CACHE) { -+ Method[] result = declaredMethodCache.get(clz); -+ if (result == null) { -+ result = clz.getMethods(); -+ for (int i = 0; i < result.length; i++) { -+ Method method = result[i]; -+ if (!method.getDeclaringClass().equals(clz)) { -+ result[i] = null; -+ } -+ } -+ declaredMethodCache.put(clz, result); - } -+ return result; - } -- -- // We have to raise privilege for getDeclaredMethods -- result = (Method[]) AccessController.doPrivileged(new PrivilegedAction() { -- public Object run() { -- return fclz.getDeclaredMethods(); -- } -- }); -- -- -- // Null out any non-public methods. -- for (int i = 0; i < result.length; i++) { -- Method method = result[i]; -- int mods = method.getModifiers(); -- if (!Modifier.isPublic(mods)) { -- result[i] = null; -- } -- } -- // Add it to the cache. -- declaredMethodCache.put(fclz, new SoftReference(result)); -- return result; - } - - //====================================================================== -diff --git a/test/java/beans/Introspector/Test5102804.java b/test/java/beans/Introspector/Test5102804.java -new file mode 100644 ---- /dev/null -+++ jdk/test/java/beans/Introspector/Test5102804.java -@@ -0,0 +1,155 @@ -+/* -+ * Copyright 2009 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 5102804 -+ * @summary Tests memory leak -+ * @author Sergey Malenkov -+ */ -+ -+import java.beans.BeanInfo; -+import java.beans.IntrospectionException; -+import java.beans.Introspector; -+import java.beans.PropertyDescriptor; -+import java.beans.SimpleBeanInfo; -+import java.lang.ref.Reference; -+import java.lang.ref.WeakReference; -+import java.net.URL; -+import java.net.URLClassLoader; -+ -+public class Test5102804 { -+ private static final String BEAN_NAME = "Test5102804$Example"; -+ private static final String BEAN_INFO_NAME = BEAN_NAME + "BeanInfo"; -+ -+ public static void main(String[] args) { -+ if (!isCollectible(getReference())) -+ throw new Error("Reference is not collected"); -+ } -+ -+ private static Reference getReference() { -+ try { -+ ClassLoader loader = new Loader(); -+ Class type = Class.forName(BEAN_NAME, true, loader); -+ if (!type.getClassLoader().equals(loader)) { -+ throw new Error("Wrong class loader"); -+ } -+ BeanInfo info = Introspector.getBeanInfo(type); -+ if (0 != info.getDefaultPropertyIndex()) { -+ throw new Error("Wrong bean info found"); -+ } -+ return new WeakReference<Class>(type); -+ } -+ catch (IntrospectionException exception) { -+ throw new Error("Introspection Error", exception); -+ } -+ catch (ClassNotFoundException exception) { -+ throw new Error("Class Not Found", exception); -+ } -+ } -+ -+ private static boolean isCollectible(Reference reference) { -+ int[] array = new int[10]; -+ while (true) { -+ try { -+ array = new int[array.length + array.length / 3]; -+ } -+ catch (OutOfMemoryError error) { -+ return null == reference.get(); -+ } -+ } -+ } -+ -+ /** -+ * Custom class loader to load the Example class by itself. -+ * Could also load it from a different code source, but this is easier to set up. -+ */ -+ private static final class Loader extends URLClassLoader { -+ Loader() { -+ super(new URL[] { -+ Test5102804.class.getProtectionDomain().getCodeSource().getLocation() -+ }); -+ } -+ -+ @Override -+ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { -+ Class c = findLoadedClass(name); -+ if (c == null) { -+ if (BEAN_NAME.equals(name) || BEAN_INFO_NAME.equals(name)) { -+ c = findClass(name); -+ } -+ else try { -+ c = getParent().loadClass(name); -+ } -+ catch (ClassNotFoundException exception) { -+ c = findClass(name); -+ } -+ } -+ if (resolve) { -+ resolveClass(c); -+ } -+ return c; -+ } -+ } -+ -+ /** -+ * A simple bean to load from the Loader class, not main class loader. -+ */ -+ public static final class Example { -+ private int value; -+ -+ public int getValue() { -+ return value; -+ } -+ -+ public void setValue(int value) { -+ this.value = value; -+ } -+ } -+ -+ /** -+ * The BeanInfo for the Example class. -+ * It is also loaded from the Loader class. -+ */ -+ public static final class ExampleBeanInfo extends SimpleBeanInfo { -+ @Override -+ public int getDefaultPropertyIndex() { -+ return 0; -+ } -+ -+ @Override -+ public PropertyDescriptor[] getPropertyDescriptors() { -+ try { -+ return new PropertyDescriptor[] { -+ new PropertyDescriptor("value", Class.forName(BEAN_NAME)) -+ }; -+ } -+ catch (ClassNotFoundException exception) { -+ return null; -+ } -+ catch (IntrospectionException exception) { -+ return null; -+ } -+ } -+ } -+} |