Skip to content

Commit

Permalink
fix apache#6742 cache Class avoid PermGen space OOM
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoheng1 committed Mar 16, 2021
1 parent d009d0c commit e585346
Showing 1 changed file with 33 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public Object invoke(Object proxy, Method method, Object[] args) {
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, Class<?>>> PROXY_CLASS_MAP = new WeakHashMap<ClassLoader, Map<String, Class<?>>>();

private static final Object PENDING_GENERATION_MARKER = new Object();

Expand Down Expand Up @@ -103,8 +105,11 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {

// get cache by class loader.
final Map<String, Object> cache;
// cache class
final Map<String, Class<?>> 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;
Expand All @@ -118,14 +123,31 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
}
}

if (value == PENDING_GENERATION_MARKER) {
try {
cache.wait();
} catch (InterruptedException e) {
// get Class by key.
Class<?> clazz = classCache.get(key);
if (null == clazz) {
if (value == PENDING_GENERATION_MARKER) {
try {
cache.wait();
} catch (InterruptedException e) {
}
} else {
cache.put(key, PENDING_GENERATION_MARKER);
break;
}
} else {
cache.put(key, PENDING_GENERATION_MARKER);
break;
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 WeakReference<Proxy>(proxy));
}
}
}
}
while (true);
Expand Down Expand Up @@ -187,7 +209,7 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
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]));
Expand All @@ -201,6 +223,10 @@ public static Proxy getProxy(ClassLoader cl, Class<?>... ics) {
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, pc);
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
Expand Down

0 comments on commit e585346

Please sign in to comment.