fix cache Class avoid PermGen space OOM in dubbo3.0 (#7386)
* fix #6742 cache Class avoid PermGen space OOM * optimization cache Class avoid PermGen space OOM * optimization cache Class avoid PermGen space OOM * Optimize Proxy WeakReference to SoftReference
This commit is contained in:
parent
d1c043f57b
commit
8e5eac1acf
|
|
@ -20,7 +20,7 @@ import org.apache.dubbo.common.utils.ClassUtils;
|
|||
import org.apache.dubbo.common.utils.ReflectUtils;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
|
@ -50,6 +50,8 @@ public abstract class Proxy {
|
|||
private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);
|
||||
private static final String PACKAGE_NAME = Proxy.class.getPackage().getName();
|
||||
private static final Map<ClassLoader, Map<String, Object>> PROXY_CACHE_MAP = new WeakHashMap<ClassLoader, Map<String, Object>>();
|
||||
// cache class, avoid PermGen OOM.
|
||||
private static final Map<ClassLoader, Map<String, Object>> PROXY_CLASS_MAP = new WeakHashMap<ClassLoader, Map<String, Object>>();
|
||||
|
||||
private static final Object PENDING_GENERATION_MARKER = new Object();
|
||||
|
||||
|
|
@ -103,8 +105,11 @@ public abstract class Proxy {
|
|||
|
||||
// get cache by class loader.
|
||||
final Map<String, Object> cache;
|
||||
// cache class
|
||||
final Map<String, Object> classCache;
|
||||
synchronized (PROXY_CACHE_MAP) {
|
||||
cache = PROXY_CACHE_MAP.computeIfAbsent(cl, k -> new HashMap<>());
|
||||
classCache = PROXY_CLASS_MAP.computeIfAbsent(cl, k -> new HashMap<>());
|
||||
}
|
||||
|
||||
Proxy proxy = null;
|
||||
|
|
@ -118,14 +123,38 @@ public abstract class Proxy {
|
|||
}
|
||||
}
|
||||
|
||||
if (value == PENDING_GENERATION_MARKER) {
|
||||
try {
|
||||
cache.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// get Class by key.
|
||||
Object clazzObj = classCache.get(key);
|
||||
if (null == clazzObj || clazzObj instanceof Reference<?>) {
|
||||
Class<?> clazz = null;
|
||||
if (clazzObj instanceof Reference<?>) {
|
||||
clazz = (Class<?>) ((Reference<?>) clazzObj).get();
|
||||
}
|
||||
|
||||
if (null == clazz) {
|
||||
if (value == PENDING_GENERATION_MARKER) {
|
||||
try {
|
||||
cache.wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
} else {
|
||||
cache.put(key, PENDING_GENERATION_MARKER);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
proxy = (Proxy) clazz.newInstance();
|
||||
return proxy;
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (null == proxy) {
|
||||
cache.remove(key);
|
||||
} else {
|
||||
cache.put(key, new SoftReference<>(proxy));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cache.put(key, PENDING_GENERATION_MARKER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
|
|
@ -190,7 +219,7 @@ public abstract class Proxy {
|
|||
ccp.setClassName(pcn);
|
||||
ccp.addField("public static java.lang.reflect.Method[] methods;");
|
||||
ccp.addField("private " + InvocationHandler.class.getName() + " handler;");
|
||||
ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{InvocationHandler.class}, new Class<?>[0], "handler=$1;");
|
||||
ccp.addConstructor(Modifier.PUBLIC, new Class<?>[] {InvocationHandler.class}, new Class<?>[0], "handler=$1;");
|
||||
ccp.addDefaultConstructor();
|
||||
Class<?> clazz = ccp.toClass();
|
||||
clazz.getField("methods").set(null, methods.toArray(new Method[0]));
|
||||
|
|
@ -204,6 +233,10 @@ public abstract class Proxy {
|
|||
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
|
||||
Class<?> pc = ccm.toClass();
|
||||
proxy = (Proxy) pc.newInstance();
|
||||
|
||||
synchronized (classCache) {
|
||||
classCache.put(key, new SoftReference<Class<?>>(pc));
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
|
|
@ -220,7 +253,7 @@ public abstract class Proxy {
|
|||
if (proxy == null) {
|
||||
cache.remove(key);
|
||||
} else {
|
||||
cache.put(key, new WeakReference<Proxy>(proxy));
|
||||
cache.put(key, new SoftReference<Proxy>(proxy));
|
||||
}
|
||||
cache.notifyAll();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue