Author: mbenson Date: Sun Sep 8 18:36:00 2013 New Revision: 1520892 URL: http://svn.apache.org/r1520892 Log: cache asm4-generated classes; do not defer to JdkProxyFactory for interface-only proxies
Modified: commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java Modified: commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java?rev=1520892&r1=1520891&r2=1520892&view=diff ============================================================================== --- commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java (original) +++ commons/proper/proxy/branches/version-2.0-work/asm4/src/main/java/org/apache/commons/proxy2/asm4/ASM4ProxyFactory.java Sun Sep 8 18:36:00 2013 @@ -24,6 +24,7 @@ import org.apache.commons.proxy2.ProxyUt import org.apache.commons.proxy2.exception.ProxyFactoryException; import org.apache.commons.proxy2.impl.AbstractProxyClassGenerator; import org.apache.commons.proxy2.impl.AbstractSubclassingProxyFactory; +import org.apache.commons.proxy2.impl.ProxyClassCache; import org.apache.xbean.asm4.ClassWriter; import org.apache.xbean.asm4.Label; import org.apache.xbean.asm4.MethodVisitor; @@ -36,36 +37,38 @@ import java.lang.reflect.InvocationHandl import java.lang.reflect.InvocationTargetException; 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.security.ProtectionDomain; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; public class ASM4ProxyFactory extends AbstractSubclassingProxyFactory { + private static final ProxyClassCache PROXY_CLASS_CACHE = new ProxyClassCache(new ProxyGenerator()); + @Override public <T> T createDelegatorProxy(final ClassLoader classLoader, final ObjectProvider<?> delegateProvider, final Class<?>... proxyClasses) { - return ProxyGenerator.newProxyInstance(classLoader, new DelegatorInvocationHandler(delegateProvider), proxyClasses); + return createProxy(classLoader, new DelegatorInvocationHandler(delegateProvider), proxyClasses); } @Override public <T> T createInterceptorProxy(final ClassLoader classLoader, final Object target, final Interceptor interceptor, final Class<?>... proxyClasses) { - return ProxyGenerator.newProxyInstance(classLoader, new InterceptorInvocationHandler(target, interceptor), proxyClasses); + return createProxy(classLoader, new InterceptorInvocationHandler(target, interceptor), proxyClasses); } @Override public <T> T createInvokerProxy(final ClassLoader classLoader, final Invoker invoker, final Class<?>... proxyClasses) { - return ProxyGenerator.newProxyInstance(classLoader, new InvokerInvocationHandler(invoker), proxyClasses); + return createProxy(classLoader, new InvokerInvocationHandler(invoker), proxyClasses); + } + + private <T> T createProxy(final ClassLoader classLoader, InvocationHandler invocationHandler, final Class<?>... proxyClasses) + { + final Class<?> proxyClass = PROXY_CLASS_CACHE.getProxyClass(classLoader, proxyClasses); + return ProxyGenerator.constructProxy(proxyClass, invocationHandler); } private static class ProxyGenerator extends AbstractProxyClassGenerator implements Opcodes @@ -75,24 +78,46 @@ public class ASM4ProxyFactory extends Ab private static final String HANDLER_NAME = "__handler"; private static final ReentrantLock LOCK = new ReentrantLock(); - public static <T> T newProxyInstance(final ClassLoader classLoader, final InvocationHandler handler, final Class<?>... classes) throws ProxyFactoryException + @Override + public Class<?> generateProxyClass(final ClassLoader classLoader, final Class<?>... proxyClasses) { - try - { - final Class<?> superclass = getSuperclass(classes); - if (superclass == Object.class) - { - @SuppressWarnings("unchecked") - final T result = (T) Proxy.newProxyInstance(classLoader, classes, handler); - return result; - } - final Class<?> proxyClass = createProxy(superclass, classLoader, getImplementationMethods(classes), toInterfaces(classes)); - return constructProxy(proxyClass, handler); - } - catch (final Exception e) - { - throw new ProxyFactoryException(e); - } + final Class<?> superclass = getSuperclass(proxyClasses); + final String proxyName = CLASSNAME_PREFIX + CLASS_NUMBER.incrementAndGet(); + final Method[] implementationMethods = getImplementationMethods(proxyClasses); + final Class<?>[] interfaces = toInterfaces(proxyClasses); + final String classFileName = proxyName.replace('.', '/'); + + try + { + return classLoader.loadClass(proxyName); + } + catch (Exception e) + { + // no-op + } + + LOCK.lock(); + try + { + try + { // Try it again, another thread may have beaten this one... + return classLoader.loadClass(proxyName); + } + catch (Exception e) + { + // no-op + } + + final byte[] proxyBytes = generateProxy(superclass, classFileName, implementationMethods, interfaces); + return Unsafe.defineClass(classLoader, superclass, proxyName, proxyBytes); + } + catch (final Exception e) + { + throw new ProxyFactoryException(e); + } + finally { + LOCK.unlock(); + } } public static <T> T constructProxy(final Class<?> clazz, final java.lang.reflect.InvocationHandler handler) throws IllegalStateException @@ -117,48 +142,6 @@ public class ASM4ProxyFactory extends Ab } } - public static Class<?> createProxy(final Class<?> classToProxy, final ClassLoader loader, final String proxyName, final Method[] methods, final Class<?>... interfaces) - { - final String classFileName = proxyName.replace('.', '/'); - - try - { - return loader.loadClass(proxyName); - } - catch (Exception e) - { - // no-op - } - - LOCK.lock(); - try - { - try - { // Try it again, another thread may have beaten this one... - return loader.loadClass(proxyName); - } - catch (Exception e) - { - // no-op - } - - final byte[] proxyBytes = generateProxy(classToProxy, classFileName, methods, interfaces); - return Unsafe.defineClass(loader, classToProxy, proxyName, proxyBytes); - } - catch (final Exception e) - { - throw new ProxyFactoryException(e); - } - finally { - LOCK.unlock(); - } - } - - public static Class<?> createProxy(final Class<?> classToProxy, final ClassLoader cl, final Method[] methods, final Class<?>... interfaces) - { - return createProxy(classToProxy, cl, CLASSNAME_PREFIX + CLASS_NUMBER.incrementAndGet(), methods, interfaces); - } - public static byte[] generateProxy(final Class<?> classToProxy, final String proxyName, final Method[] methods, final Class<?>... interfaces) throws ProxyFactoryException { final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); @@ -180,15 +163,6 @@ public class ASM4ProxyFactory extends Ab // push InvocationHandler fields cw.visitField(ACC_FINAL + ACC_PRIVATE, HANDLER_NAME, "Ljava/lang/reflect/InvocationHandler;", null, null).visitEnd(); - final Map<String, List<Method>> methodMap = new HashMap<String, List<Method>>(); - - findMethods(classToProxy, methodMap); - - for (final Class<?> anInterface : interfaces) - { - findMethods(anInterface, methodMap); - } - for (final Method method : methods) { processMethod(cw, method, proxyClassFileName, HANDLER_NAME); @@ -197,53 +171,7 @@ public class ASM4ProxyFactory extends Ab return cw.toByteArray(); } - private static void findMethods(Class<?> clazz, final Map<String, List<Method>> methodMap) - { - while (clazz != null) { - for (final Method method : clazz.getDeclaredMethods()) - { - final int modifiers = method.getModifiers(); - - if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) - { - continue; - } - - List<Method> methods = methodMap.get(method.getName()); - if (methods == null) - { - methods = new ArrayList<Method>(); - methods.add(method); - methodMap.put(method.getName(), methods); - } - else if (!isOverridden(methods, method)) - { - methods.add(method); - } - } - - clazz = clazz.getSuperclass(); - } - } - - private static boolean isOverridden(final List<Method> methods, final Method method) - { - for (final Method m : methods) - { - if (Arrays.equals(m.getParameterTypes(), method.getParameterTypes())) - { - return true; - } - } - return false; - } - private static void processMethod(final ClassWriter cw, final Method method, final String proxyName, final String handlerName) throws ProxyFactoryException { - if ("<init>".equals(method.getName())) - { - return; - } - final Class<?> returnType = method.getReturnType(); final Class<?>[] parameterTypes = method.getParameterTypes(); final Class<?>[] exceptionTypes = method.getExceptionTypes(); @@ -758,12 +686,6 @@ public class ASM4ProxyFactory extends Ab return className.replace('.', '/'); } - @Override // not used ATM - public Class<?> generateProxyClass(final ClassLoader classLoader, final Class<?>... proxyClasses) - { - return createProxy(getSuperclass(proxyClasses), classLoader, getImplementationMethods(proxyClasses), toInterfaces(proxyClasses)); - } - private static class Unsafe { // sun.misc.Unsafe