CLOUDSTACK-6859:Management Server PermGen run out of memory after some

time due to class leak.
This commit is contained in:
Min Chen 2014-06-06 23:44:30 -07:00
parent 3b3f4577b0
commit 25580c7cd1

View File

@ -21,10 +21,11 @@ package org.apache.cloudstack.framework.async;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.MethodProxy;
@ -39,6 +40,7 @@ public class AsyncCallbackDispatcher<T, R> implements AsyncCompletionCallback {
private Object _contextObject; private Object _contextObject;
private Object _resultObject; private Object _resultObject;
private AsyncCallbackDriver _driver = new InplaceAsyncCallbackDriver(); private AsyncCallbackDriver _driver = new InplaceAsyncCallbackDriver();
private static Map<Class, Enhancer> enMap = new HashMap<Class, Enhancer>();
private AsyncCallbackDispatcher(T target) { private AsyncCallbackDispatcher(T target) {
assert (target != null); assert (target != null);
@ -58,39 +60,45 @@ public class AsyncCallbackDispatcher<T, R> implements AsyncCompletionCallback {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T getTarget() { public T getTarget() {
Enhancer en = new Enhancer();
Class<?> clz = _targetObject.getClass(); Class<?> clz = _targetObject.getClass();
String clzName = clz.getName(); String clzName = clz.getName();
if (clzName.contains("EnhancerByCloudStack")) if (clzName.contains("EnhancerByCloudStack"))
clz = clz.getSuperclass(); clz = clz.getSuperclass();
en.setSuperclass(clz);
en.setCallbacks(new Callback[] {new MethodInterceptor() { Enhancer en = null;
@Override synchronized (enMap) {
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { en = enMap.get(clz);
_callbackMethod = arg1; if (en == null) {
_callbackMethod.setAccessible(true); en = new Enhancer();
return null;
en.setSuperclass(clz);
en.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
return null;
}
});
enMap.put(clz, en);
} }
}, new MethodInterceptor() { }
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
return null;
}
}});
en.setCallbackFilter(new CallbackFilter() {
@Override
public int accept(Method method) {
if (method.getParameterTypes().length == 0 && method.getName().equals("finalize")) {
return 1;
}
return 0;
}
});
try { try {
return (T)en.create(); T t = (T)en.create();
Factory factory = (Factory)t;
factory.setCallback(0, new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
if (arg1.getParameterTypes().length == 0 && arg1.getName().equals("finalize")) {
return null;
} else {
_callbackMethod = arg1;
_callbackMethod.setAccessible(true);
return null;
}
}
});
return t;
} catch (Throwable e) { } catch (Throwable e) {
s_logger.error("Unexpected exception", e); s_logger.error("Unexpected exception", e);
} }