diff options
author | Andy Clement <aclement@pivotal.io> | 2017-09-28 16:03:17 -0700 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2017-10-20 13:11:32 -0700 |
commit | e908c89ef235e55519fa37042d156605c4366e35 (patch) | |
tree | 3279a11a5efdb65614c87adc1d093f3bdbf54ef7 /weaver5/java5-src/org/aspectj/weaver | |
parent | d2659f6c5823e321fec4b6021c2524f1c259527a (diff) | |
download | aspectj-e908c89ef235e55519fa37042d156605c4366e35.tar.gz aspectj-e908c89ef235e55519fa37042d156605c4366e35.zip |
Fixes Bug 525293 - Spring AOP could be faster
Multiple changes here:
- annotation unpacking is smarter and if it only needs runtime
retention annotations it uses reflection and doesn't unpack the
bytes to discover class level retention annotations.
- Reflection worlds are shared if for the same classloader.
Diffstat (limited to 'weaver5/java5-src/org/aspectj/weaver')
-rw-r--r-- | weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java | 142 |
1 files changed, 69 insertions, 73 deletions
diff --git a/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java index a978d9605..016becf87 100644 --- a/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java +++ b/weaver5/java5-src/org/aspectj/weaver/reflect/Java15AnnotationFinder.java @@ -1,13 +1,10 @@ /* ******************************************************************* - * Copyright (c) 2005 Contributors. + * Copyright (c) 2005, 2017 Contributors. * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 * which accompanies this distribution and is available at * http://eclipse.org/legal/epl-v10.html - * - * Contributors: - * Adrian Colyer Initial implementation * ******************************************************************/ package org.aspectj.weaver.reflect; @@ -17,15 +14,13 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; import org.aspectj.apache.bcel.classfile.AnnotationDefault; import org.aspectj.apache.bcel.classfile.Attribute; import org.aspectj.apache.bcel.classfile.JavaClass; import org.aspectj.apache.bcel.classfile.LocalVariable; import org.aspectj.apache.bcel.classfile.LocalVariableTable; +import org.aspectj.apache.bcel.util.ClassLoaderRepository; import org.aspectj.apache.bcel.util.NonCachingClassLoaderRepository; import org.aspectj.apache.bcel.util.Repository; import org.aspectj.weaver.AnnotationAJ; @@ -36,36 +31,44 @@ import org.aspectj.weaver.bcel.BcelAnnotation; import org.aspectj.weaver.bcel.BcelWeakClassLoaderReference; /** - * Find the given annotation (if present) on the given object * + * @author Adrian Colyer + * @author Andy Clement */ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { + public static final ResolvedType[][] NO_PARAMETER_ANNOTATIONS = new ResolvedType[][] {}; + private Repository bcelRepository; private BcelWeakClassLoaderReference classLoaderRef; private World world; + private static boolean useCachingClassLoaderRepository; + + static { + try { + useCachingClassLoaderRepository = System.getProperty("Xset:bcelRepositoryCaching","true").equalsIgnoreCase("true"); + } catch (Throwable t) { + useCachingClassLoaderRepository = false; + } + } // must have no-arg constructor for reflective construction public Java15AnnotationFinder() { } public void setClassLoader(ClassLoader aLoader) { - // TODO: No easy way to ask the world factory for the right kind of - // repository so - // default to the safe one! (pr160674) this.classLoaderRef = new BcelWeakClassLoaderReference(aLoader); - this.bcelRepository = new NonCachingClassLoaderRepository(classLoaderRef); + if (useCachingClassLoaderRepository) { + this.bcelRepository = new ClassLoaderRepository(classLoaderRef); + } else { + this.bcelRepository = new NonCachingClassLoaderRepository(classLoaderRef); + } } public void setWorld(World aWorld) { this.world = aWorld; } - /* - * (non-Javadoc) - * - * @see org.aspectj.weaver.reflect.AnnotationFinder#getAnnotation(org.aspectj .weaver.ResolvedType, java.lang.Object) - */ public Object getAnnotation(ResolvedType annotationType, Object onObject) { try { Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) Class.forName(annotationType.getName(), @@ -155,7 +158,6 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { } catch (ClassNotFoundException cnfEx) { // just use reflection then } - return null; } @@ -186,80 +188,76 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { } catch (ClassNotFoundException cnfEx) { // just use reflection then } - return null; } - public Set getAnnotations(Member onMember) { - if (!(onMember instanceof AccessibleObject)) - return Collections.EMPTY_SET; - // here we really want both the runtime visible AND the class visible - // annotations - // so we bail out to Bcel and then chuck away the JavaClass so that we - // don't hog - // memory. - try { - JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass()); - org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0]; - if (onMember instanceof Method) { - org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember); - if (bcelMethod == null) { - // fallback on reflection - see pr220430 - // System.err.println( - // "Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '" - // + - // onMember.getName()+"' in class '"+jc.getClassName()+"'"); - } else { - anns = bcelMethod.getAnnotations(); + public ResolvedType[] getAnnotations(Member onMember, boolean areRuntimeAnnotationsSufficient) { + if (!(onMember instanceof AccessibleObject)) { + return ResolvedType.NONE; + } + // If annotations with class level retention are required then we need to open + // open the class file. If only runtime retention annotations are required + // we can just use reflection. + if (!areRuntimeAnnotationsSufficient) { + try { + JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass()); + org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = null; + if (onMember instanceof Method) { + org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember); + if (bcelMethod != null) { + anns = bcelMethod.getAnnotations(); + } + } else if (onMember instanceof Constructor) { + org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) onMember); + anns = bcelCons.getAnnotations(); + } else if (onMember instanceof Field) { + org.aspectj.apache.bcel.classfile.Field bcelField = jc.getField((Field) onMember); + anns = bcelField.getAnnotations(); } - } else if (onMember instanceof Constructor) { - org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) onMember); - anns = bcelCons.getAnnotations(); - } else if (onMember instanceof Field) { - org.aspectj.apache.bcel.classfile.Field bcelField = jc.getField((Field) onMember); - anns = bcelField.getAnnotations(); - } - // the answer is cached and we don't want to hold on to memory - bcelRepository.clear(); - // OPTIMIZE make this a constant 0 size array - if (anns == null) - anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0]; - // convert to our Annotation type - Set<ResolvedType> annSet = new HashSet<ResolvedType>(); - for (int i = 0; i < anns.length; i++) { - annSet.add(world.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature()))); + // the answer is cached and we don't want to hold on to memory + bcelRepository.clear(); + if (anns == null || anns.length == 0) { + return ResolvedType.NONE; + } + ResolvedType[] annotationTypes = new ResolvedType[anns.length]; + for (int i = 0; i < anns.length; i++) { + annotationTypes[i] = world.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature())); + } + return annotationTypes; + } catch (ClassNotFoundException cnfEx) { + // just use reflection then } - return annSet; - } catch (ClassNotFoundException cnfEx) { - // just use reflection then } AccessibleObject ao = (AccessibleObject) onMember; Annotation[] anns = ao.getDeclaredAnnotations(); - Set<UnresolvedType> annSet = new HashSet<UnresolvedType>(); + if (anns.length == 0) { + return ResolvedType.NONE; + } + ResolvedType[] annotationTypes = new ResolvedType[anns.length]; for (int i = 0; i < anns.length; i++) { - annSet.add(UnresolvedType.forName(anns[i].annotationType().getName()).resolve(world)); + annotationTypes[i] = UnresolvedType.forName(anns[i].annotationType().getName()).resolve(world); } - return annSet; + return annotationTypes; } public ResolvedType[] getAnnotations(Class forClass, World inWorld) { // here we really want both the runtime visible AND the class visible - // annotations - // so we bail out to Bcel and then chuck away the JavaClass so that we - // don't hog - // memory. + // annotations so we bail out to Bcel and then chuck away the JavaClass so that we + // don't hog memory. try { JavaClass jc = bcelRepository.loadClass(forClass); org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = jc.getAnnotations(); bcelRepository.clear(); - if (anns == null) + if (anns == null) { return ResolvedType.NONE; - ResolvedType[] ret = new ResolvedType[anns.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = inWorld.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature())); + } else { + ResolvedType[] ret = new ResolvedType[anns.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = inWorld.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature())); + } + return ret; } - return ret; } catch (ClassNotFoundException cnfEx) { // just use reflection then } @@ -313,8 +311,6 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { return ret; } - public static final ResolvedType[][] NO_PARAMETER_ANNOTATIONS = new ResolvedType[][] {}; - public ResolvedType[][] getParameterAnnotationTypes(Member onMember) { if (!(onMember instanceof AccessibleObject)) return NO_PARAMETER_ANNOTATIONS; |