OPENJPA-1113 - Revert changes back to previous levels: Reflection:743396 & AbstractBrokerFactory 768588. I have verified that the latest changes associated to this issue did not caused any memory leak by observing/dumping the static cache sizes in the Reflection class. The emf.close() method cleared out the cache, i.e. HashMap.size() == 0. From looking at the memory usage of the JVM that invoked the test in persistence-jdbc module, the memory usage continues to grow even without the changes committed by this issue. Therefore there is some memory leak somewhere either in the test case or the provider code. The OOM condition only occurs with Sun JDK, IBM JDK works ok.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@781473 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Albert Lee 2009-06-03 16:58:14 +00:00
parent 9168ab0032
commit 4d5c43ad78
2 changed files with 19 additions and 89 deletions

View File

@ -21,22 +21,20 @@ package org.apache.openjpa.enhance;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.WeakHashMap;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.Reflectable;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.UserException;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.UserException;
/**
* Reflection utilities used to support and augment enhancement. Used both
@ -49,84 +47,27 @@ public class Reflection {
private static final Localizer _loc = Localizer.forPackage
(Reflection.class);
// Weak HashMap caches of getter/setter/beanProperty methods
private static Map<Class<?>, Map<String, Method>> getterMethodCache =
new WeakHashMap<Class<?>, Map<String, Method>>();
private static Map<Class<?>, Map<String, Method>> setterMethodCache =
new WeakHashMap<Class<?>, Map<String, Method>>();
private static Map<Class<?>, Set<String>> beanPropertiesNameCache =
new WeakHashMap<Class<?>, Set<String>>();
private static Method getGetterMethod(Class<?> cls, String prop) {
Method rtnMethod = null;
Map<String, Method> clsMap = getterMethodCache.get(cls);
if (clsMap != null) {
rtnMethod = clsMap.get(prop);
}
return rtnMethod;
}
private static void setGetterMethod(Class<?> cls, String prop,
Method method) {
Map<String, Method> clsMap = getterMethodCache.get(cls);
if (clsMap == null) {
clsMap = new HashMap<String, Method>();
getterMethodCache.put(cls, clsMap);
}
clsMap.put(prop, method);
}
private static Method getSetterMethod(Class<?> cls, String prop) {
Method rtnMethod = null;
Map<String, Method> clsMap = setterMethodCache.get(cls);
if (clsMap != null) {
rtnMethod = clsMap.get(prop);
}
return rtnMethod;
}
private static void setSetterMethod(Class<?> cls, String prop,
Method method) {
Map<String, Method> clsMap = setterMethodCache.get(cls);
if (clsMap == null) {
clsMap = new HashMap<String, Method>();
setterMethodCache.put(cls, clsMap);
}
clsMap.put(prop, method);
}
public static void flushCaches() {
getterMethodCache.clear();
setterMethodCache.clear();
beanPropertiesNameCache.clear();
}
/**
* Return the getter method matching the given property name, optionally
* throwing an exception if none.
*/
public static Method findGetter(Class cls, String prop, boolean mustExist) {
Method m = getGetterMethod(cls, prop);
if (m != null) {
return m;
}
String capProp = StringUtils.capitalize(prop);
prop = StringUtils.capitalize(prop);
String name = "get" + prop;
Method m;
try {
// this algorithm searches for a get<prop> or is<prop> method in
// a breadth-first manner.
for (Class c = cls; c != null && c != Object.class;
c = c.getSuperclass()) {
m = getDeclaredMethod(c, "get" + capProp, null);
m = getDeclaredMethod(c, name, null);
if (m != null) {
setGetterMethod(cls, prop, m);
return m;
} else {
m = getDeclaredMethod(c, "is" + capProp, null);
m = getDeclaredMethod(c, "is" + prop, null);
if (m != null && (m.getReturnType() == boolean.class
|| m.getReturnType() == Boolean.class)) {
setGetterMethod(cls, prop, m);
|| m.getReturnType() == Boolean.class))
return m;
}
}
}
} catch (Exception e) {
@ -154,19 +95,14 @@ public class Reflection {
*/
public static Method findSetter(Class cls, String prop, Class param,
boolean mustExist) {
Method m = getSetterMethod(cls, prop);
if (m != null) {
return m;
}
String name = "set" + StringUtils.capitalize(prop);
Method m;
try {
for (Class c = cls; c != null && c != Object.class;
c = c.getSuperclass()) {
m = getDeclaredMethod(c, name, param);
if (m != null) {
setSetterMethod(cls, prop, m);
if (m != null)
return m;
}
}
} catch (Exception e) {
throw new GeneralException(e);
@ -838,14 +774,10 @@ public class Reflection {
public static Set<String> getBeanStylePropertyNames(Class c) {
if (c == null)
return Collections.EMPTY_SET;
Set<String> result = beanPropertiesNameCache.get(c);
if (result != null) {
return result;
}
Method[] methods = c.getMethods();
if (methods == null || methods.length < 2)
return Collections.EMPTY_SET;
/*Set<String>*/ result = new TreeSet<String>();
Set<String> result = new TreeSet<String>();
for (Method m : methods) {
if (m.getName().startsWith("get")) {
if (!canReflect(m))
@ -863,7 +795,6 @@ public class Reflection {
}
}
}
beanPropertiesNameCache.put(c, result);
return result;
}

View File

@ -31,26 +31,23 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.apache.commons.collections.set.MapBackedSet;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.conf.BrokerValue;
import org.apache.commons.collections.set.MapBackedSet;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.conf.OpenJPAVersion;
import org.apache.openjpa.conf.BrokerValue;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.datacache.DataCacheStoreManager;
import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.enhance.ManagedClassSubclasser;
import org.apache.openjpa.enhance.PCRegistry;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.enhance.ManagedClassSubclasser;
import org.apache.openjpa.event.BrokerFactoryEvent;
import org.apache.openjpa.event.RemoteCommitEventManager;
import org.apache.openjpa.lib.conf.Configuration;
@ -58,7 +55,9 @@ import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.openjpa.lib.util.concurrent.ConcurrentReferenceHashSet;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.util.GeneralException;
import org.apache.openjpa.util.InvalidStateException;
@ -411,7 +410,7 @@ public abstract class AbstractBrokerFactory
PCRegistry.removeRegisterClassListener
(_conf.getMetaDataRepositoryInstance());
}
Reflection.flushCaches();
_conf.close();
_closed = true;
Log log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);