diff options
9 files changed, 128 insertions, 11 deletions
diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java index cb2c01f7d6..a597f8b1ee 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/CglibProxyFactory.java @@ -149,4 +149,7 @@ public class CglibProxyFactory implements ProxyFactory { } + public void removeProxiesForContribution(ClassLoader contributionClassloader){ + // do nothing, no cache to clear + } } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java index 049c73f258..3cb9445d2d 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ExtensibleProxyFactory.java @@ -122,4 +122,7 @@ public class ExtensibleProxyFactory implements ProxyFactory { return interfaceFactory.isProxyClass(clazz) || (classFactory != null && classFactory.isProxyClass(clazz)); } + public void removeProxiesForContribution(ClassLoader contributionClassloader){ + // do nothing, no cache to clear + } } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java index f2d272757d..8d9612315a 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/ProxyFactory.java @@ -84,5 +84,13 @@ public interface ProxyFactory { * @return true if the class is a generated proxy class by this factory */ boolean isProxyClass(Class<?> clazz); + + /** + * Allow cached proxies to be removed when a contribution is removed. The proxy + * cache holds the application interface so will pin the contribution classloader + * + * @param contributionClassloader the classloader of the contribution being removed + */ + void removeProxiesForContribution(ClassLoader contributionClassloader); } diff --git a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java index a9a28d434a..7163357042 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java @@ -24,11 +24,15 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Future; +import javax.xml.bind.JAXBContext; import javax.xml.ws.AsyncHandler; import javax.xml.ws.Response; @@ -213,4 +217,32 @@ public class JDKProxyFactory implements ProxyFactory, LifeCycleListener { public void stop() { cache.clear(); } + + public void removeProxiesForContribution(ClassLoader contributionClassloader){ + try { + synchronized(cache) { + Set<Class<?>> objSet = cache.keySet(); + List<Class<?>> toRemove = new ArrayList<Class<?>>(); + Iterator<Class<?>> i = objSet.iterator(); + loop: + while(i.hasNext()) { + Class<?> cls = i.next(); + ClassLoader cl = cls.getClassLoader(); + while (cl != null){ + if (cl == contributionClassloader){ + toRemove.add(cls); + break loop; + } + // take account of generated classes + cl = cl.getParent(); + } + } + for (Class<?> cls : toRemove){ + cache.remove(cls); + } + } + } catch(Exception e) { + throw new ServiceRuntimeException(e); + } + } } diff --git a/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java b/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java index 456c4ef7b6..27f00be0ba 100644 --- a/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java +++ b/sca-java-2.x/trunk/modules/domain-node/src/main/java/org/apache/tuscany/sca/impl/NodeImpl.java @@ -54,6 +54,8 @@ import org.apache.tuscany.sca.contribution.resolver.ModelResolver; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.core.invocation.ProxyFactory; +import org.apache.tuscany.sca.core.invocation.ProxyFactoryExtensionPoint; import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper; import org.apache.tuscany.sca.deployment.Deployer; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; @@ -90,6 +92,8 @@ public class NodeImpl implements Node { private boolean quietLogging; private boolean releaseOnUnload; + + private ContributionListener contributionListener; public NodeImpl(Deployer deployer, CompositeActivator compositeActivator, @@ -107,7 +111,7 @@ public class NodeImpl implements Node { utilityExtensionPoint.getUtility(ActiveNodes.class).getActiveNodes().add(this); - domainRegistry.addContributionListener(new ContributionListener() { + contributionListener = new ContributionListener() { public void contributionInstalled(String uri) { // Do nothing } @@ -126,7 +130,9 @@ public class NodeImpl implements Node { } } } - }); + }; + + this.domainRegistry.addContributionListener(contributionListener); endpointsIncludeDomainName = !TuscanyRuntime.DEFAUL_DOMAIN_NAME.equals(domainRegistry.getDomainName()); @@ -248,6 +254,10 @@ public class NodeImpl implements Node { JavaInterfaceFactory javaInterfaceFactory = factoryExtensionPoint.getFactory(JavaInterfaceFactory.class); javaInterfaceFactory.removeInterfacesForContribution(contributionClassloader); + + ProxyFactoryExtensionPoint proxyFactoryExtensionPoint = extensionPointRegistry.getExtensionPoint(ProxyFactoryExtensionPoint.class); + ProxyFactory interfaceProxyFactory = proxyFactoryExtensionPoint.getInterfaceProxyFactory(); + interfaceProxyFactory.removeProxiesForContribution(contributionClassloader); } domainRegistry.uninstallContribution(contributionURI); @@ -587,6 +597,7 @@ public class NodeImpl implements Node { startedComposites.clear(); stoppedComposites.clear(); extensionPointRegistry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(ActiveNodes.class).getActiveNodes().remove(this); + domainRegistry.removeContributionListener(contributionListener); if (tuscanyRuntime != null) { tuscanyRuntime.stop(); } diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java index ca39ec0e62..923d13cd5e 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/BaseBeanGenerator.java @@ -20,6 +20,7 @@ package org.apache.tuscany.sca.interfacedef.java.jaxws; import java.lang.annotation.Annotation; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -119,8 +120,8 @@ public abstract class BaseBeanGenerator implements Opcodes { JAVA_KEYWORDS.put("enum", "_enum"); } - protected static final Map<Object, Class<?>> generatedClasses = - Collections.synchronizedMap(new WeakHashMap<Object, Class<?>>()); + protected static final Map<Object, WeakReference<Class<?>>> generatedClasses = + Collections.synchronizedMap(new WeakHashMap<Object, WeakReference<Class<?>>>()); protected XMLAdapterExtensionPoint xmlAdapters; diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java index 2e82428f7e..28fd2afe73 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/FaultBeanGenerator.java @@ -23,6 +23,7 @@ import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; +import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -108,7 +109,11 @@ public class FaultBeanGenerator extends BaseBeanGenerator { public Class<?> generate(Class<? extends Throwable> exceptionClass, GeneratedClassLoader cl, Operation operation) { synchronized (exceptionClass) { QName element = getElementName(exceptionClass, operation); - Class<?> faultBeanClass = generatedClasses.get(element); + WeakReference<Class<?>> wr = generatedClasses.get(element); + Class<?> faultBeanClass = null; + if (wr != null){ + faultBeanClass = wr.get(); + } if (faultBeanClass == null) { // TUSCANY-3283 - all generated classes (including exception) should go in the namespace @@ -122,7 +127,7 @@ public class FaultBeanGenerator extends BaseBeanGenerator { String classSignature = "L" + classDescriptor + ";"; faultBeanClass = generate(classDescriptor, classSignature, namespace, name, getProperties(exceptionClass), cl); - generatedClasses.put(element, faultBeanClass); + generatedClasses.put(element, new WeakReference<Class<?>>(faultBeanClass)); } return faultBeanClass; } diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java index 42151464a4..ab7036c0ce 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/WrapperBeanGenerator.java @@ -20,6 +20,7 @@ package org.apache.tuscany.sca.interfacedef.java.jaxws; import java.lang.annotation.Annotation; +import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -64,7 +65,11 @@ public class WrapperBeanGenerator extends BaseBeanGenerator { GeneratedClassLoader cl) { synchronized (m.getDeclaringClass()) { MethodKey key = new MethodKey(m, true); - Class<?> wrapperClass = generatedClasses.get(key); + WeakReference<Class<?>> wr = generatedClasses.get(key); + Class<?> wrapperClass = null; + if (wr != null){ + wrapperClass = wr.get(); + } if (wrapperClass == null) { String wrapperClassDescriptor = wrapperClassName.replace('.', '/'); String wrapperClassSignature = "L" + wrapperClassDescriptor + ";"; @@ -110,7 +115,7 @@ public class WrapperBeanGenerator extends BaseBeanGenerator { wrapperClass = generate(wrapperClassDescriptor, wrapperClassSignature, wrapperNamespace, wrapperName, properties .toArray(new BeanProperty[properties.size()]), cl); - generatedClasses.put(key, wrapperClass); + generatedClasses.put(key, new WeakReference<Class<?>>(wrapperClass)); } return wrapperClass; @@ -134,7 +139,11 @@ public class WrapperBeanGenerator extends BaseBeanGenerator { GeneratedClassLoader cl) { synchronized (m.getDeclaringClass()) { MethodKey key = new MethodKey(m, false); - Class<?> wrapperClass = generatedClasses.get(key); + WeakReference<Class<?>> wr = generatedClasses.get(key); + Class<?> wrapperClass = null; + if (wr != null){ + wrapperClass = wr.get(); + } if (wrapperClass == null) { String wrapperClassDescriptor = wrapperClassName.replace('.', '/'); String wrapperClassSignature = "L" + wrapperClassDescriptor + ";"; @@ -212,7 +221,7 @@ public class WrapperBeanGenerator extends BaseBeanGenerator { wrapperClass = generate(wrapperClassDescriptor, wrapperClassSignature, wrapperNamespace, wrapperName, properties .toArray(new BeanProperty[properties.size()]), cl); - generatedClasses.put(key, wrapperClass); + generatedClasses.put(key, new WeakReference<Class<?>>(wrapperClass)); } return wrapperClass; diff --git a/sca-java-2.x/trunk/testing/itest/performance/performance-test/src/test/java/org/apache/tuscany/sca/test/performance/PerformanceTestCase.java b/sca-java-2.x/trunk/testing/itest/performance/performance-test/src/test/java/org/apache/tuscany/sca/test/performance/PerformanceTestCase.java index 329eea6a3d..d05ed1fd74 100644 --- a/sca-java-2.x/trunk/testing/itest/performance/performance-test/src/test/java/org/apache/tuscany/sca/test/performance/PerformanceTestCase.java +++ b/sca-java-2.x/trunk/testing/itest/performance/performance-test/src/test/java/org/apache/tuscany/sca/test/performance/PerformanceTestCase.java @@ -78,6 +78,33 @@ public class PerformanceTestCase { resultsFile.flush();
resultsFile.close();
}
+
+ @Test
+ public void testNodeStartStop() {
+ dumpHeapStart("testInstallUninstall");
+
+ printRuntimeStats("createRuntime");
+
+ createRuntime();
+
+ callNodeStartStopRepeatedly(100);
+
+ waitForInput();
+
+ dumpHeapEnd("testInstallUninstall_postNodeStop");
+
+ printRuntimeStats("stopRuntime");
+
+ stopRuntime();
+
+ printRuntimeStats("destroyRuntime");
+
+ destroyRuntime();
+
+ printRuntimeStats("End");
+
+ dumpHeapEnd("testInstallUninstall_postStop");
+ }
@Test
public void testInstallUninstall() {
@@ -91,7 +118,7 @@ public class PerformanceTestCase { createNode();
- callInstallUninstallRepeatedly(10);
+ callInstallUninstallRepeatedly(100);
dumpHeapEnd("testInstallUninstall_postUninstall");
@@ -187,6 +214,24 @@ public class PerformanceTestCase { // ============================================================
+ public void callNodeStartStopRepeatedly(int repeatCount) {
+ for (int i =0; i < repeatCount; i++){
+ printRuntimeStats("createNode");
+
+ createNode();
+
+ callInstallUninstallRepeatedly(1);
+
+ printRuntimeStats("stopNode");
+
+ stopNode();
+
+ printRuntimeStats("destroyNode");
+
+ destroyNode();
+ }
+ }
+
public void callInstallUninstallRepeatedly(int repeatCount) {
for (int i =0; i < repeatCount; i++){
printRuntimeStats("install/unistall contribution");
|