Updated Branches: refs/heads/5.3 9afb9b692 -> 8b23962c4
Cache result of determining method/constructor location - another hotspot found in high volume applications Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/8b23962c Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/8b23962c Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/8b23962c Branch: refs/heads/5.3 Commit: 8b23962c48076aa90e8e81b89de0e5f3234ca498 Parents: 9afb9b6 Author: Howard M. Lewis Ship <[email protected]> Authored: Fri May 25 13:58:49 2012 -0700 Committer: Howard M. Lewis Ship <[email protected]> Committed: Fri May 25 14:00:27 2012 -0700 ---------------------------------------------------------------------- .../services/ComponentInstantiatorSourceImpl.java | 3 +- .../apache/tapestry5/services/TapestryModule.java | 26 ++++- .../internal/AbstractReloadableObjectCreator.java | 10 ++- .../tapestry5/ioc/internal/RegistryImpl.java | 2 +- .../ioc/internal/ReloadableObjectCreator.java | 7 +- .../internal/ReloadableObjectCreatorSource.java | 6 +- ...loadableServiceImplementationObjectCreator.java | 13 ++- .../internal/services/PlasticProxyFactoryImpl.java | 79 ++++++++++++--- .../ioc/services/PlasticProxyFactory.java | 35 +++++-- 9 files changed, 136 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java index afac15d..2ee4d49 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ComponentInstantiatorSourceImpl.java @@ -1,4 +1,4 @@ -// Copyright 2006, 2007, 2008, 2010, 2011 The Apache Software Foundation +// Copyright 2006, 2007, 2008, 2010, 2011, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -174,6 +174,7 @@ public final class ComponentInstantiatorSourceImpl implements ComponentInstantia { changeTracker.clear(); classToInstantiator.clear(); + proxyFactory.clearCache(); // Release the existing class pool, loader and so forth. // Create a new one. http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java ---------------------------------------------------------------------- diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java index e2561d0..04c9365 100644 --- a/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java +++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java @@ -1234,9 +1234,10 @@ public final class TapestryModule * href="https://issues.apache.org/jira/browse/TAP5-79">TAP5-79</a> for details. There are no longer any built-in * contributions to the configuration. * - * @param configuration contributions of special factories for some constants, each - * contributed factory may return a - * binding if applicable, or null otherwise + * @param configuration + * contributions of special factories for some constants, each + * contributed factory may return a + * binding if applicable, or null otherwise */ public BindingFactory buildPropBindingFactory(List<BindingFactory> configuration, @Autobuild PropBindingFactory service) @@ -2222,7 +2223,8 @@ public final class TapestryModule * <p/> * This contributes "class", "properties" and "tml" (the template extension). * - * @param configuration collection of extensions + * @param configuration + * collection of extensions */ public static void contributeResourceDigestGenerator(Configuration<String> configuration) { @@ -2694,7 +2696,8 @@ public final class TapestryModule * even if a user overrides the default * service implementation. * - * @param defaultSource The service to decorate + * @param defaultSource + * The service to decorate * @param environment */ public static FieldValidatorDefaultSource decorateFieldValidatorDefaultSource( @@ -2898,4 +2901,17 @@ public final class TapestryModule { configuration.add("LocalhostOnly", new LocalhostOnly()); } + + @Startup + public static void registerToClearPlasticProxyFactoryOnInvalidation(@ComponentClasses InvalidationEventHub hub, @Builtin final PlasticProxyFactory proxyFactory) + { + hub.addInvalidationListener(new InvalidationListener() + { + @Override + public void objectWasInvalidated() + { + proxyFactory.clearCache(); + } + }); + } } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java index ed69717..0bd464d 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/AbstractReloadableObjectCreator.java @@ -1,4 +1,4 @@ -// Copyright 2010, 2011 The Apache Software Foundation +// Copyright 2010, 2011, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,6 +28,7 @@ import org.apache.tapestry5.ioc.ReloadAware; import org.apache.tapestry5.ioc.internal.util.CollectionFactory; import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.internal.util.URLChangeTracker; +import org.apache.tapestry5.ioc.services.PlasticProxyFactory; import org.apache.tapestry5.services.UpdateListener; import org.slf4j.Logger; @@ -51,6 +52,8 @@ public abstract class AbstractReloadableObjectCreator implements ObjectCreator, private final URLChangeTracker changeTracker = new URLChangeTracker(); + private final PlasticProxyFactory proxyFactory; + /** * The set of class names that should be loaded by the class loader. This is necessary to support * reloading the class when a base class changes, and to properly support access to protected methods. @@ -63,9 +66,10 @@ public abstract class AbstractReloadableObjectCreator implements ObjectCreator, private PlasticClassLoader loader; - protected AbstractReloadableObjectCreator(ClassLoader baseClassLoader, String implementationClassName, + protected AbstractReloadableObjectCreator(PlasticProxyFactory proxyFactory, ClassLoader baseClassLoader, String implementationClassName, Logger logger, OperationTracker tracker) { + this.proxyFactory = proxyFactory; this.baseClassLoader = baseClassLoader; this.implementationClassName = implementationClassName; this.logger = logger; @@ -89,6 +93,8 @@ public abstract class AbstractReloadableObjectCreator implements ObjectCreator, loader = null; + proxyFactory.clearCache(); + boolean reloadNow = informInstanceOfReload(); instance = reloadNow ? createInstance() : null; http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java index 12a7c54..b1c35f1 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/RegistryImpl.java @@ -1097,7 +1097,7 @@ public class RegistryImpl implements Registry, InternalRegistry, ServiceProxyPro private <T> T createReloadingProxy(Class<T> interfaceClass, final Class<? extends T> implementationClass, ObjectLocator locator) { - ReloadableObjectCreator creator = new ReloadableObjectCreator(implementationClass.getClassLoader(), + ReloadableObjectCreator creator = new ReloadableObjectCreator(proxyFactory, implementationClass.getClassLoader(), implementationClass.getName(), loggerSource.getLogger(implementationClass), this, locator); getService(UpdateListenerHub.class).addUpdateListener(creator); http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreator.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreator.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreator.java index 48c802b..b54da52 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreator.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreator.java @@ -1,4 +1,4 @@ -// Copyright 2010 The Apache Software Foundation +// Copyright 2010, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.apache.tapestry5.ioc.internal; import org.apache.tapestry5.ioc.ObjectLocator; import org.apache.tapestry5.ioc.OperationTracker; +import org.apache.tapestry5.ioc.services.PlasticProxyFactory; import org.slf4j.Logger; /** @@ -25,10 +26,10 @@ public class ReloadableObjectCreator extends AbstractReloadableObjectCreator { private final ObjectLocator locator; - public ReloadableObjectCreator(ClassLoader baseClassLoader, String implementationClassName, Logger logger, + public ReloadableObjectCreator(PlasticProxyFactory proxyFactory, ClassLoader baseClassLoader, String implementationClassName, Logger logger, OperationTracker tracker, ObjectLocator locator) { - super(baseClassLoader, implementationClassName, logger, tracker); + super(proxyFactory, baseClassLoader, implementationClassName, logger, tracker); this.locator = locator; } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java index 8e5dd82..2bf35f7 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableObjectCreatorSource.java @@ -1,4 +1,4 @@ -// Copyright 2010, 2011 The Apache Software Foundation +// Copyright 2010, 2011, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -73,13 +73,15 @@ public class ReloadableObjectCreatorSource implements ObjectCreatorSource private Object createReloadableProxy(ServiceBuilderResources resources) { - ReloadableServiceImplementationObjectCreator reloadableCreator = new ReloadableServiceImplementationObjectCreator( + ReloadableServiceImplementationObjectCreator reloadableCreator = new ReloadableServiceImplementationObjectCreator(proxyFactory, resources, proxyFactory.getClassLoader(), serviceImplementationClass.getName()); resources.getService(UpdateListenerHub.class).addUpdateListener(reloadableCreator); if (eagerLoad) + { reloadableCreator.createObject(); + } return proxyFactory.createProxy(serviceInterfaceClass, reloadableCreator, getDescription()); } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java index 31611eb..93baf33 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/ReloadableServiceImplementationObjectCreator.java @@ -1,4 +1,4 @@ -// Copyright 2010 The Apache Software Foundation +// Copyright 2010, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,11 +14,12 @@ package org.apache.tapestry5.ioc.internal; -import java.lang.reflect.Constructor; - import org.apache.tapestry5.ioc.ObjectCreator; import org.apache.tapestry5.ioc.ServiceBuilderResources; import org.apache.tapestry5.ioc.internal.util.InternalUtils; +import org.apache.tapestry5.ioc.services.PlasticProxyFactory; + +import java.lang.reflect.Constructor; /** * Returns an {@link ObjectCreator} for lazily instantiating a given implementation class (with dependencies). @@ -30,10 +31,10 @@ public class ReloadableServiceImplementationObjectCreator extends AbstractReload { private final ServiceBuilderResources resources; - public ReloadableServiceImplementationObjectCreator(ServiceBuilderResources resources, ClassLoader baseClassLoader, - String implementationClassName) + public ReloadableServiceImplementationObjectCreator(PlasticProxyFactory proxyFactory, ServiceBuilderResources resources, ClassLoader baseClassLoader, + String implementationClassName) { - super(baseClassLoader, implementationClassName, resources.getLogger(), resources.getTracker()); + super(proxyFactory, baseClassLoader, implementationClassName, resources.getLogger(), resources.getTracker()); this.resources = resources; } http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java index 440078b..45bf82e 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/PlasticProxyFactoryImpl.java @@ -1,4 +1,4 @@ -// Copyright 2011 The Apache Software Foundation +// Copyright 2011, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import org.apache.tapestry5.internal.plastic.asm.Type; import org.apache.tapestry5.internal.plastic.asm.tree.*; import org.apache.tapestry5.ioc.Location; import org.apache.tapestry5.ioc.ObjectCreator; +import org.apache.tapestry5.ioc.internal.util.CollectionFactory; import org.apache.tapestry5.ioc.internal.util.InternalUtils; import org.apache.tapestry5.ioc.services.PlasticProxyFactory; import org.apache.tapestry5.plastic.*; @@ -28,11 +29,14 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.List; +import java.util.Map; public class PlasticProxyFactoryImpl implements PlasticProxyFactory { private final PlasticManager manager; + private final Map<String, Location> memberToLocation = CollectionFactory.newConcurrentMap(); + public PlasticProxyFactoryImpl(ClassLoader parentClassLoader, Logger logger) { this(PlasticManager.withClassLoader(parentClassLoader).create(), logger); @@ -109,35 +113,78 @@ public class PlasticProxyFactoryImpl implements PlasticProxyFactory return bytecode == null ? null : PlasticInternalUtils.convertBytecodeToClassNode(bytecode); } - public Location getMethodLocation(Method method) + public Location getMethodLocation(final Method method) { + ObjectCreator<String> descriptionCreator = new ObjectCreator<String>() + { + @Override + public String createObject() + { + return InternalUtils.asString(method); + } + }; + return getMemberLocation(method, method.getName(), Type.getMethodDescriptor(method), - InternalUtils.asString(method)); + descriptionCreator); } - public Location getConstructorLocation(Constructor constructor) + public Location getConstructorLocation(final Constructor constructor) { - StringBuilder builder = new StringBuilder(constructor.getDeclaringClass().getName()).append("("); - String sep = ""; - - for (Class parameterType : constructor.getParameterTypes()) + ObjectCreator<String> descriptionCreator = new ObjectCreator<String>() { - builder.append(sep); - builder.append(parameterType.getSimpleName()); + @Override + public String createObject() + { + StringBuilder builder = new StringBuilder(constructor.getDeclaringClass().getName()).append("("); + String sep = ""; - sep = ", "; - } + for (Class parameterType : constructor.getParameterTypes()) + { + builder.append(sep); + builder.append(parameterType.getSimpleName()); - builder.append(")"); + sep = ", "; + } - String constructorDescription = builder.toString(); + builder.append(")"); + + return builder.toString(); + } + }; return getMemberLocation(constructor, "<init>", Type.getConstructorDescriptor(constructor), - constructorDescription); + descriptionCreator); + } + + @Override + public void clearCache() + { + memberToLocation.clear(); + } + + + public Location getMemberLocation(Member member, String methodName, String memberTypeDesc, ObjectCreator<String> textDescriptionCreator) + { + String className = member.getDeclaringClass().getName(); + + String key = className + ":" + methodName + ":" + memberTypeDesc; + + Location location = memberToLocation.get(key); + + if (location == null) + { + location = constructMemberLocation(member, methodName, memberTypeDesc, textDescriptionCreator.createObject()); + + memberToLocation.put(key, location); + } + + return location; + } - public Location getMemberLocation(Member member, String methodName, String memberTypeDesc, String textDescription) + private Location constructMemberLocation(Member member, String methodName, String memberTypeDesc, String textDescription) { + ClassNode classNode = readClassNode(member.getDeclaringClass()); if (classNode == null) http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b23962c/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java ---------------------------------------------------------------------- diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java index e8099c3..81e1eac 100644 --- a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java +++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/PlasticProxyFactory.java @@ -1,4 +1,4 @@ -// Copyright 2011 The Apache Software Foundation +// Copyright 2011, 2012 The Apache Software Foundation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,8 +42,10 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub * Creates a proxy object that implements the indicated interface, then invokes the callback to further * configure the proxy. * - * @param interfaceType interface implemented by proxy - * @param callback configures the proxy + * @param interfaceType + * interface implemented by proxy + * @param callback + * configures the proxy * @return instantiator that can be used to create an instance of the proxy class */ <T> ClassInstantiator<T> createProxy(Class<T> interfaceType, PlasticClassTransformer callback); @@ -53,7 +55,8 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub * used in the cases where encapsulating the PlasticClass construction into a {@linkplain PlasticClassTransformer * callback} is not feasible (which is the case for some of the older APIs inside Tapestry IoC). * - * @param interfaceType class proxy will extend from + * @param interfaceType + * class proxy will extend from * @return transformation from which an instantiator may be created */ <T> PlasticClassTransformation<T> createProxyTransformation(Class<T> interfaceType); @@ -64,10 +67,14 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub * creator implementation may decide to * cache the return value as appropriate). * - * @param <T> type of proxy - * @param interfaceType interface class for proxy - * @param creator object responsible for creating the real object - * @param description the <code>toString()</code> of the proxy + * @param <T> + * type of proxy + * @param interfaceType + * interface class for proxy + * @param creator + * object responsible for creating the real object + * @param description + * the <code>toString()</code> of the proxy * @return proxy instance */ <T> T createProxy(Class<T> interfaceType, ObjectCreator<T> creator, String description); @@ -75,7 +82,8 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub /** * Converts a method to a {@link Location}, which includes information about the source file name and line number. * - * @param method to look up + * @param method + * to look up * @return the location (identifying the method and possibly, the line number within the method) */ Location getMethodLocation(Method method); @@ -87,4 +95,13 @@ public interface PlasticProxyFactory extends PlasticClassListenerHub * @return the location (identifying the constructor and possibly, the line number within the method) */ Location getConstructorLocation(Constructor constructor); + + /** + * Clears any cached information stored by the proxy factory; this is useful in Tapestry development mode + * when a class loader may have been discarded (because the proxy factory may indirectly keep references + * to classes loaded by the old class loader). + * + * @since 5.3.3 + */ + void clearCache(); }
