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();
+ }
}