Repository: cloudstack Updated Branches: refs/heads/master 3b3f4577b -> 25580c7cd
CLOUDSTACK-6859:Management Server PermGen run out of memory after some time due to class leak. Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/25580c7c Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/25580c7c Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/25580c7c Branch: refs/heads/master Commit: 25580c7cd1a484feba1960612c9a4ae1a179cbff Parents: 3b3f457 Author: Min Chen <min.c...@citrix.com> Authored: Fri Jun 6 23:44:30 2014 -0700 Committer: Min Chen <min.c...@citrix.com> Committed: Fri Jun 6 23:57:26 2014 -0700 ---------------------------------------------------------------------- .../async/AsyncCallbackDispatcher.java | 62 +++++++++++--------- 1 file changed, 35 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/25580c7c/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java ---------------------------------------------------------------------- diff --git a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java index 06cfcff..b9aa12b 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/async/AsyncCallbackDispatcher.java @@ -21,10 +21,11 @@ package org.apache.cloudstack.framework.async; import java.lang.reflect.InvocationTargetException; 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.Factory; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; @@ -39,6 +40,7 @@ public class AsyncCallbackDispatcher<T, R> implements AsyncCompletionCallback { private Object _contextObject; private Object _resultObject; private AsyncCallbackDriver _driver = new InplaceAsyncCallbackDriver(); + private static Map<Class, Enhancer> enMap = new HashMap<Class, Enhancer>(); private AsyncCallbackDispatcher(T target) { assert (target != null); @@ -58,39 +60,45 @@ public class AsyncCallbackDispatcher<T, R> implements AsyncCompletionCallback { @SuppressWarnings("unchecked") public T getTarget() { - Enhancer en = new Enhancer(); - Class<?> clz = _targetObject.getClass(); String clzName = clz.getName(); if (clzName.contains("EnhancerByCloudStack")) clz = clz.getSuperclass(); - en.setSuperclass(clz); - en.setCallbacks(new Callback[] {new MethodInterceptor() { - @Override - public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { - _callbackMethod = arg1; - _callbackMethod.setAccessible(true); - return null; - } - }, 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; + + Enhancer en = null; + synchronized (enMap) { + en = enMap.get(clz); + if (en == null) { + en = new Enhancer(); + + 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); } - }); + } 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) { s_logger.error("Unexpected exception", e); }