You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2016/09/14 02:53:26 UTC

svn commit: r1760618 - in /aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl: AsyncService.java AsyncServiceFactory.java

Author: timothyjward
Date: Wed Sep 14 02:53:26 2016
New Revision: 1760618

URL: http://svn.apache.org/viewvc?rev=1760618&view=rev
Log:
[ARIES-1603] Weakly cache mediator classes to reduce ClassLoader creation rates

Modified:
    aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncService.java
    aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncServiceFactory.java

Modified: aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncService.java
URL: http://svn.apache.org/viewvc/aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncService.java?rev=1760618&r1=1760617&r2=1760618&view=diff
==============================================================================
--- aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncService.java (original)
+++ aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncService.java Wed Sep 14 02:53:26 2016
@@ -18,17 +18,18 @@
  */
 package org.apache.aries.async.impl;
 
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutorService;
 
-import net.sf.cglib.proxy.Enhancer;
-
 import org.osgi.framework.Bundle;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.wiring.BundleWiring;
@@ -37,6 +38,8 @@ import org.osgi.service.log.LogService;
 import org.osgi.util.promise.Promise;
 import org.osgi.util.tracker.ServiceTracker;
 
+import net.sf.cglib.proxy.Enhancer;
+
 
 public class AsyncService implements Async {
 
@@ -62,6 +65,21 @@ public class AsyncService implements Asy
 		}
 	}
 
+	/**
+	 * It is important to use both weak keys *and* values in this map. The
+	 * key must be weakly held because it is typically a type from another 
+	 * bundle, and would represent a classloader leak if held after that 
+	 * bundle was uninstalled. The value must be weak because it either 
+	 * extends or implements the type that is the key, and so holds a strong 
+	 * reference to the key, which again would cause a leak.
+	 * 
+	 * This cache may drop the value type if no mediators are held, however in
+	 * this situation we can simply create a new value without risking exploding
+	 * the heap.
+	 */
+	private final WeakHashMap<Class<?>, WeakReference<Class<?>>> proxyLoaderCache
+		= new WeakHashMap<Class<?>, WeakReference<Class<?>>>();
+	
 	private final Bundle clientBundle;
 	
 	private final ConcurrentMap<Thread, MethodCall> invocations = new ConcurrentHashMap<Thread, MethodCall>();
@@ -76,6 +94,10 @@ public class AsyncService implements Asy
 		this.executor = executor;
 		this.logServiceTracker = logServiceTracker;
 	}
+	
+	void clear() {
+		proxyLoaderCache.clear();
+	}
 
 	public <T> T mediate(final T service, final Class<T> iface) {
 		return AccessController.doPrivileged(new PrivilegedAction<T>() {
@@ -91,7 +113,11 @@ public class AsyncService implements Asy
 		TrackingInvocationHandler handler = new TrackingInvocationHandler(this, 
 				clientBundle, logServiceTracker, service);
 		
-		if(iface.isInterface()) {
+		T toReturn = cachedMediate(iface, handler);
+		
+		if(toReturn != null) {
+			return toReturn;
+		} else if(iface.isInterface()) {
 			return (T) Proxy.newProxyInstance(
 					new ClassLoader(service.getClass().getClassLoader()){}, 
 					new Class[] {iface}, handler);
@@ -101,6 +127,25 @@ public class AsyncService implements Asy
 		}
 	}
 
+	@SuppressWarnings("unchecked")
+	private <T> T cachedMediate(Class<T> iface, TrackingInvocationHandler handler) {
+		WeakReference<Class<?>> weakReference = proxyLoaderCache.get(iface);
+		Class<?> cached = weakReference == null ? null : weakReference.get();
+		if(cached != null) {
+			if(iface.isInterface()) {
+				try {
+					return (T) cached.getConstructor(InvocationHandler.class)
+							.newInstance(handler);
+				} catch (Exception e) {
+					throw new IllegalArgumentException("Unable to mediate interface: " + iface, e);
+				}
+			} else {
+				return (T) Enhancer.create(cached, handler);
+			}
+		}
+		return null;
+	}
+
 	public <T> T mediate(final ServiceReference<? extends T> ref, final Class<T> iface) {
 		return AccessController.doPrivileged(new PrivilegedAction<T>() {
 			public T run() {
@@ -115,7 +160,11 @@ public class AsyncService implements Asy
 		TrackingInvocationHandler handler = new TrackingInvocationHandler(this, 
 				clientBundle, logServiceTracker, ref);
 		
-		if(iface.isInterface()) {
+		T toReturn = cachedMediate(iface, handler);
+		
+		if(toReturn != null) {
+			return toReturn;
+		} else if(iface.isInterface()) {
 			return (T) Proxy.newProxyInstance(
 					new ClassLoader(iface.getClassLoader()){}, 
 					new Class[] {iface}, handler);

Modified: aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncServiceFactory.java
URL: http://svn.apache.org/viewvc/aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncServiceFactory.java?rev=1760618&r1=1760617&r2=1760618&view=diff
==============================================================================
--- aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncServiceFactory.java (original)
+++ aries/trunk/async/async-impl/src/main/java/org/apache/aries/async/impl/AsyncServiceFactory.java Wed Sep 14 02:53:26 2016
@@ -45,6 +45,8 @@ public class AsyncServiceFactory impleme
 	}
 
 	public void ungetService(Bundle bundle,
-			ServiceRegistration<Async> registration, Async service) {}
+			ServiceRegistration<Async> registration, Async service) {
+		((AsyncService) service).clear();
+	}
 
 }