diff --git a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java index e3c59556b..15bb647c4 100644 --- a/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java +++ b/bcel-builder/src/main/java/org/aspectj/apache/bcel/util/ClassLoaderRepository.java @@ -64,6 +64,7 @@ import java.net.URLClassLoader; import java.util.AbstractMap; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; @@ -74,11 +75,11 @@ import org.aspectj.apache.bcel.util.ClassLoaderRepository.SoftHashMap.SpecialVal /** * The repository maintains information about which classes have been loaded. - * + * * It loads its data from the ClassLoader implementation passed into its constructor. - * + * * @see org.aspectj.apache.bcel.Repository - * + * * @version $Id: ClassLoaderRepository.java,v 1.13 2009/09/09 19:56:20 aclement Exp $ * @author M. Dahm * @author David Dixon-Peugh @@ -92,10 +93,20 @@ public class ClassLoaderRepository implements Repository { private static SoftHashMap /* */sharedCache = new SoftHashMap(Collections.synchronizedMap(new HashMap())); // For fast translation of the classname *intentionally not static* - private SoftHashMap /* */nameMap = new SoftHashMap(new HashMap(), false); + private SoftHashMap /* */ nameMap = new SoftHashMap(new HashMap(), false); public static boolean useSharedCache = System.getProperty("org.aspectj.apache.bcel.useSharedCache", "true").equalsIgnoreCase("true"); + //Cache not found classes as well to prevent unnecessary file I/O operations + public static final boolean useUnavailableClassesCache = + System.getProperty("org.aspectj.apache.bcel.useUnavailableClassesCache", "true").equalsIgnoreCase("true"); + //Ignore cache clear requests to not build up the cache over and over again + public static final boolean ignoreCacheClearRequests = + System.getProperty("org.aspectj.apache.bcel.ignoreCacheClearRequests", "true").equalsIgnoreCase("true"); + + //Second cache for the unavailable classes + private static Set unavailableClasses = new HashSet(); + private static int cacheHitsShared = 0; private static int missSharedEvicted = 0; // Misses in shared cache access due to reference GC private long timeManipulatingURLs = 0L; @@ -105,6 +116,16 @@ public class ClassLoaderRepository implements Repository { private int cacheHitsLocal = 0; private int missLocalEvicted = 0; // Misses in local cache access due to reference GC + // private static int cntHitFromCache = 0; + // private static int cntLoadAndParseClass = 0; + // private static int cntClassPutInCache = 0; + // private static int cntClassRemovedFromCache = 0; + // private static int cntCacheCleared = 0; + // private static int cntLoadClassCount = 0; + // private static int cntClassNotFound = 0; + // private static int cntClassNotFoundViaCache; + // private static int cntValueFromCacheGotGarbageCollected; + public ClassLoaderRepository(java.lang.ClassLoader loader) { this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader()); } @@ -163,6 +184,7 @@ public class ClassLoaderRepository implements Repository { if (value.get() == null) { // it got GC'd map.remove(value.key); + // cntValueFromCacheGotGarbageCollected++; if (recordMiss) missSharedEvicted++; return null; @@ -184,8 +206,12 @@ public class ClassLoaderRepository implements Repository { @Override public void clear() { - processQueue(); - map.clear(); + if (!ignoreCacheClearRequests) + { + // cntCacheCleared++; + processQueue(); + map.clear(); + } } @Override @@ -211,6 +237,7 @@ public class ClassLoaderRepository implements Repository { * Store a new JavaClass into this repository as a soft reference and return the reference */ private void storeClassAsReference(URL url, JavaClass clazz) { + // cntClassPutInCache++; if (useSharedCache) { clazz.setRepository(null); // can't risk setting repository, we'll get in a pickle! sharedCache.put(url, clazz); @@ -231,6 +258,7 @@ public class ClassLoaderRepository implements Repository { * Remove class from repository */ public void removeClass(JavaClass clazz) { + // cntClassRemovedFromCache++; if (useSharedCache) sharedCache.remove(toURL(clazz.getClassName())); else @@ -282,12 +310,32 @@ public class ClassLoaderRepository implements Repository { */ public JavaClass loadClass(String className) throws ClassNotFoundException { + // cntLoadClassCount++; + // if (cntLoadClassCount % 10000 == 0) + // { + // logStatistics(); + // } + + //Quick evaluation of unavailable classes to prevent unnecessary file I/O + if (useUnavailableClassesCache && unavailableClasses.contains(className)) + { + // cntClassNotFoundViaCache++; + throw new ClassNotFoundException(className + " not found."); + } + // translate to a URL long time = System.currentTimeMillis(); java.net.URL url = toURL(className); timeManipulatingURLs += (System.currentTimeMillis() - time); if (url == null) + { + // cntClassNotFound++; + if (useUnavailableClassesCache) + { + unavailableClasses.add(className); + } throw new ClassNotFoundException(className + " not found - unable to determine URL"); + } JavaClass clazz = null; @@ -296,11 +344,13 @@ public class ClassLoaderRepository implements Repository { clazz = findClassShared(url); if (clazz != null) { cacheHitsShared++; + // cntHitFromCache++; return clazz; } } else { clazz = findClassLocal(url); if (clazz != null) { + // cntHitFromCache++; cacheHitsLocal++; return clazz; } @@ -313,12 +363,18 @@ public class ClassLoaderRepository implements Repository { // Load it String classFile = className.replace('.', '/'); InputStream is = (useSharedCache ? url.openStream() : loaderRef.getClassLoader().getResourceAsStream( - classFile + ".class")); + classFile + ".class")); if (is == null) { + // cntClassNotFound++; + if (useUnavailableClassesCache) + { + unavailableClasses.add(className); + } throw new ClassNotFoundException(className + " not found using url " + url); } ClassParser parser = new ClassParser(is, className); clazz = parser.parse(); + // cntLoadAndParseClass++; // Cache it storeClassAsReference(url, clazz); @@ -327,6 +383,8 @@ public class ClassLoaderRepository implements Repository { classesLoadedCount++; return clazz; } catch (IOException e) { + // cntClassNotFound++; + unavailableClasses.add(className); throw new ClassNotFoundException(e.toString()); } } @@ -361,7 +419,7 @@ public class ClassLoaderRepository implements Repository { */ public long[] reportStats() { return new long[] { timeSpentLoading, timeManipulatingURLs, classesLoadedCount, cacheHitsShared, missSharedEvicted, - cacheHitsLocal, missLocalEvicted, sharedCache.size() }; + cacheHitsLocal, missLocalEvicted, sharedCache.size() }; } /** @@ -385,10 +443,36 @@ public class ClassLoaderRepository implements Repository { /** Clear all entries from the local cache */ public void clear() { - if (useSharedCache) - sharedCache.clear(); - else - localCache.clear(); + if (!ignoreCacheClearRequests) + { + if (useSharedCache) + sharedCache.clear(); + else + localCache.clear(); + } } + // public void logStatistics() + // { + // //print out some statistic somewhere at the end + // StringBuffer sb = new StringBuffer(); + // sb.append("****************************************\n"); + // sb.append("NonCachingClassLoaderRepository: " + this.toString() + "\n"); + // sb.append("cntHitFromCache: " + cntHitFromCache + "\n"); + // sb.append("cntLoadAndParseClass:" + cntLoadAndParseClass + "\n"); + // sb.append("cntClassPutInCache: " + cntClassPutInCache + "\n"); + // sb.append("cntClassNotFound: " + cntClassNotFound + "\n"); + // sb.append("cntClassNotFoundViaCache: " + cntClassNotFoundViaCache + "\n"); + // //sb.append("cacheSizeNotFoundClasses: " + unavailableClasses.size() + "\n"); + // sb.append("cacheSize: " + sharedCache.size() + "\n"); + // sb.append("cntClassRemovedFromCache: " + cntClassRemovedFromCache + "\n"); + // sb.append("cntValueFromCacheGotGarbageCollected: " + cntValueFromCacheGotGarbageCollected + "\n"); + // sb.append("cntCacheCleared: " + cntCacheCleared + "\n"); + // sb.append("cntLoadClassCount: " + cntLoadClassCount + "\n"); + // sb.append("****************************************\n"); + // System.out.println(sb.toString()); + // + // System.out.println(report()); + // } + } diff --git a/weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java b/weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java index 016becf87..920f6feb1 100644 --- a/weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java +++ b/weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java @@ -1,11 +1,8 @@ -/* ******************************************************************* - * 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 - * ******************************************************************/ +/* + * ******************************************************************* 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 + ******************************************************************/ package org.aspectj.weaver.reflect; import java.lang.annotation.Annotation; @@ -31,90 +28,145 @@ import org.aspectj.weaver.bcel.BcelAnnotation; import org.aspectj.weaver.bcel.BcelWeakClassLoaderReference; /** - * * @author Adrian Colyer * @author Andy Clement */ -public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { +public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder +{ - public static final ResolvedType[][] NO_PARAMETER_ANNOTATIONS = new ResolvedType[][] {}; + public static final ResolvedType[][] NO_PARAMETER_ANNOTATIONS = new ResolvedType[][]{}; private Repository bcelRepository; private BcelWeakClassLoaderReference classLoaderRef; + + private static Repository staticBcelRepository; + private static BcelWeakClassLoaderReference staticClassLoaderRef; + private World world; private static boolean useCachingClassLoaderRepository; - - static { - try { - useCachingClassLoaderRepository = System.getProperty("Xset:bcelRepositoryCaching","true").equalsIgnoreCase("true"); - } catch (Throwable t) { + + //Use single instance of Repository and ClassLoader + public static final boolean useSingleInstances = + System.getProperty("org.aspectj.apache.bcel.useSingleRepositoryInstance", "true").equalsIgnoreCase("true"); + + 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 Java15AnnotationFinder() + { } - public void setClassLoader(ClassLoader aLoader) { - this.classLoaderRef = new BcelWeakClassLoaderReference(aLoader); - if (useCachingClassLoaderRepository) { - this.bcelRepository = new ClassLoaderRepository(classLoaderRef); - } else { - this.bcelRepository = new NonCachingClassLoaderRepository(classLoaderRef); + public void setClassLoader(ClassLoader aLoader) + { + //Set class loader ref + if (useSingleInstances && staticClassLoaderRef == null) + staticClassLoaderRef = new BcelWeakClassLoaderReference(aLoader); + else + this.classLoaderRef = new BcelWeakClassLoaderReference(aLoader); + + //Set repository + if (useCachingClassLoaderRepository) + { + if (useSingleInstances && staticBcelRepository == null) + staticBcelRepository = new ClassLoaderRepository(getClassLoader()); + else + this.bcelRepository = new ClassLoaderRepository(getClassLoader()); + } + else + { + if (useSingleInstances && staticBcelRepository == null) + staticBcelRepository = new NonCachingClassLoaderRepository(getClassLoader()); + else + this.bcelRepository = new NonCachingClassLoaderRepository(getClassLoader()); } } - public void setWorld(World aWorld) { + private ClassLoader getClassLoader() + { + return useSingleInstances ? staticClassLoaderRef.getClassLoader() : classLoaderRef.getClassLoader(); + } + + private Repository getBcelRepository() + { + return useSingleInstances ? staticBcelRepository : bcelRepository; + } + + public void setWorld(World aWorld) + { this.world = aWorld; } - public Object getAnnotation(ResolvedType annotationType, Object onObject) { - try { - Class annotationClass = (Class) Class.forName(annotationType.getName(), + public Object getAnnotation(ResolvedType annotationType, Object onObject) + { + try + { + Class annotationClass = + (Class) Class.forName(annotationType.getName(), false, getClassLoader()); - if (onObject.getClass().isAnnotationPresent(annotationClass)) { + if (onObject.getClass().isAnnotationPresent(annotationClass)) + { return onObject.getClass().getAnnotation(annotationClass); } - } catch (ClassNotFoundException ex) { + } + catch (ClassNotFoundException ex) + { // just return null } return null; } - public Object getAnnotationFromClass(ResolvedType annotationType, Class aClass) { - try { - Class annotationClass = (Class) Class.forName(annotationType.getName(), + public Object getAnnotationFromClass(ResolvedType annotationType, Class aClass) + { + try + { + Class annotationClass = + (Class) Class.forName(annotationType.getName(), false, getClassLoader()); - if (aClass.isAnnotationPresent(annotationClass)) { + if (aClass.isAnnotationPresent(annotationClass)) + { return aClass.getAnnotation(annotationClass); } - } catch (ClassNotFoundException ex) { + } + catch (ClassNotFoundException ex) + { // just return null } return null; } - public Object getAnnotationFromMember(ResolvedType annotationType, Member aMember) { + public Object getAnnotationFromMember(ResolvedType annotationType, Member aMember) + { if (!(aMember instanceof AccessibleObject)) return null; AccessibleObject ao = (AccessibleObject) aMember; - try { + try + { Class annotationClass = Class.forName(annotationType.getName(), false, getClassLoader()); - if (ao.isAnnotationPresent(annotationClass)) { + if (ao.isAnnotationPresent(annotationClass)) + { return ao.getAnnotation(annotationClass); } - } catch (ClassNotFoundException ex) { + } + catch (ClassNotFoundException ex) + { // just return null } return null; } - private ClassLoader getClassLoader() { - return classLoaderRef.getClassLoader(); - } - - public AnnotationAJ getAnnotationOfType(UnresolvedType ofType, Member onMember) { + public AnnotationAJ getAnnotationOfType(UnresolvedType ofType, Member onMember) + { if (!(onMember instanceof AccessibleObject)) return null; // here we really want both the runtime visible AND the class visible @@ -122,62 +174,84 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { // 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) { + try + { + JavaClass jc = getBcelRepository().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) { + if (bcelMethod == null) + { // pr220430 // System.err.println( // "Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '" // + // onMember.getName()+"' in class '"+jc.getClassName()+"'"); - } else { + } + else + { anns = bcelMethod.getAnnotations(); } - } else if (onMember instanceof Constructor) { + } + else if (onMember instanceof Constructor) + { org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) onMember); anns = bcelCons.getAnnotations(); - } else if (onMember instanceof Field) { + } + 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(); + getBcelRepository().clear(); // OPTIMIZE make constant 0 size array for sharing if (anns == null) anns = new org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[0]; // convert to our Annotation type - for (int i = 0; i < anns.length; i++) { - if (anns[i].getTypeSignature().equals(ofType.getSignature())) { + for (int i = 0; i < anns.length; i++) + { + if (anns[i].getTypeSignature().equals(ofType.getSignature())) + { return new BcelAnnotation(anns[i], world); } } return null; - } catch (ClassNotFoundException cnfEx) { + } + catch (ClassNotFoundException cnfEx) + { // just use reflection then } return null; } - public String getAnnotationDefaultValue(Member onMember) { - try { - JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass()); - if (onMember instanceof Method) { + public String getAnnotationDefaultValue(Member onMember) + { + try + { + JavaClass jc = getBcelRepository().loadClass(onMember.getDeclaringClass()); + if (onMember instanceof Method) + { org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember); - if (bcelMethod == null) { + if (bcelMethod == null) + { // pr220430 // System.err.println( // "Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '" // + // onMember.getName()+"' in class '"+jc.getClassName()+"'"); - } else { + } + else + { Attribute[] attrs = bcelMethod.getAttributes(); - for (int i = 0; i < attrs.length; i++) { + for (int i = 0; i < attrs.length; i++) + { Attribute attribute = attrs[i]; - if (attribute.getName().equals("AnnotationDefault")) { + if (attribute.getName().equals("AnnotationDefault")) + { AnnotationDefault def = (AnnotationDefault) attribute; return def.getElementValue().stringifyValue(); } @@ -185,133 +259,171 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { return null; } } - } catch (ClassNotFoundException cnfEx) { + } + catch (ClassNotFoundException cnfEx) + { // just use reflection then } return null; } - public ResolvedType[] getAnnotations(Member onMember, boolean areRuntimeAnnotationsSufficient) { - if (!(onMember instanceof AccessibleObject)) { + 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()); + if (!areRuntimeAnnotationsSufficient) + { + try + { + JavaClass jc = getBcelRepository().loadClass(onMember.getDeclaringClass()); org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = null; - if (onMember instanceof Method) { + if (onMember instanceof Method) + { org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember); - if (bcelMethod != null) { + if (bcelMethod != null) + { anns = bcelMethod.getAnnotations(); } - } else if (onMember instanceof Constructor) { + } + else if (onMember instanceof Constructor) + { org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) onMember); anns = bcelCons.getAnnotations(); - } else if (onMember instanceof Field) { + } + 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(); - if (anns == null || anns.length == 0) { + getBcelRepository().clear(); + if (anns == null || anns.length == 0) + { return ResolvedType.NONE; } ResolvedType[] annotationTypes = new ResolvedType[anns.length]; - for (int i = 0; i < anns.length; i++) { + for (int i = 0; i < anns.length; i++) + { annotationTypes[i] = world.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature())); } return annotationTypes; - } catch (ClassNotFoundException cnfEx) { + } + catch (ClassNotFoundException cnfEx) + { // just use reflection then } } AccessibleObject ao = (AccessibleObject) onMember; Annotation[] anns = ao.getDeclaredAnnotations(); - if (anns.length == 0) { + if (anns.length == 0) + { return ResolvedType.NONE; } ResolvedType[] annotationTypes = new ResolvedType[anns.length]; - for (int i = 0; i < anns.length; i++) { + for (int i = 0; i < anns.length; i++) + { annotationTypes[i] = UnresolvedType.forName(anns[i].annotationType().getName()).resolve(world); } return annotationTypes; } - public ResolvedType[] getAnnotations(Class forClass, World inWorld) { + 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. - try { - JavaClass jc = bcelRepository.loadClass(forClass); + try + { + JavaClass jc = getBcelRepository().loadClass(forClass); org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = jc.getAnnotations(); - bcelRepository.clear(); - if (anns == null) { + getBcelRepository().clear(); + if (anns == null) + { return ResolvedType.NONE; - } else { + } + else + { ResolvedType[] ret = new ResolvedType[anns.length]; - for (int i = 0; i < ret.length; i++) { + for (int i = 0; i < ret.length; i++) + { ret[i] = inWorld.resolve(UnresolvedType.forSignature(anns[i].getTypeSignature())); } return ret; } - } catch (ClassNotFoundException cnfEx) { + } + catch (ClassNotFoundException cnfEx) + { // just use reflection then } Annotation[] classAnnotations = forClass.getAnnotations(); ResolvedType[] ret = new ResolvedType[classAnnotations.length]; - for (int i = 0; i < classAnnotations.length; i++) { + for (int i = 0; i < classAnnotations.length; i++) + { ret[i] = inWorld.resolve(classAnnotations[i].annotationType().getName()); } return ret; } - public String[] getParameterNames(Member forMember) { + public String[] getParameterNames(Member forMember) + { if (!(forMember instanceof AccessibleObject)) return null; - try { - JavaClass jc = bcelRepository.loadClass(forMember.getDeclaringClass()); + try + { + JavaClass jc = getBcelRepository().loadClass(forMember.getDeclaringClass()); LocalVariableTable lvt = null; int numVars = 0; - if (forMember instanceof Method) { + if (forMember instanceof Method) + { org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) forMember); lvt = bcelMethod.getLocalVariableTable(); numVars = bcelMethod.getArgumentTypes().length; - } else if (forMember instanceof Constructor) { + } + else if (forMember instanceof Constructor) + { org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) forMember); lvt = bcelCons.getLocalVariableTable(); numVars = bcelCons.getArgumentTypes().length; } return getParameterNamesFromLVT(lvt, numVars); - } catch (ClassNotFoundException cnfEx) { + } + catch (ClassNotFoundException cnfEx) + { ; // no luck } return null; } - private String[] getParameterNamesFromLVT(LocalVariableTable lvt, int numVars) { + private String[] getParameterNamesFromLVT(LocalVariableTable lvt, int numVars) + { if (lvt == null) return null;// pr222987 - prevent NPE LocalVariable[] vars = lvt.getLocalVariableTable(); - if (vars.length < numVars) { + if (vars.length < numVars) + { // basic error, we can't get the names... return null; } String[] ret = new String[numVars]; - for (int i = 0; i < numVars; i++) { + for (int i = 0; i < numVars; i++) + { ret[i] = vars[i + 1].getName(); } return ret; } - public ResolvedType[][] getParameterAnnotationTypes(Member onMember) { + public ResolvedType[][] getParameterAnnotationTypes(Member onMember) + { if (!(onMember instanceof AccessibleObject)) return NO_PARAMETER_ANNOTATIONS; // here we really want both the runtime visible AND the class visible @@ -319,63 +431,85 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { // 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()); + try + { + JavaClass jc = getBcelRepository().loadClass(onMember.getDeclaringClass()); org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[][] anns = null; - if (onMember instanceof Method) { + if (onMember instanceof Method) + { org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember); - if (bcelMethod == null) { + if (bcelMethod == null) + { // pr220430 // System.err.println( // "Unexpected problem in Java15AnnotationFinder: cannot retrieve annotations on method '" // + // onMember.getName()+"' in class '"+jc.getClassName()+"'"); - } else { + } + else + { anns = bcelMethod.getParameterAnnotations(); } - } else if (onMember instanceof Constructor) { + } + else if (onMember instanceof Constructor) + { org.aspectj.apache.bcel.classfile.Method bcelCons = jc.getMethod((Constructor) onMember); anns = bcelCons.getParameterAnnotations(); - } else if (onMember instanceof Field) { + } + else if (onMember instanceof Field) + { // anns = null; } // the answer is cached and we don't want to hold on to memory - bcelRepository.clear(); + getBcelRepository().clear(); if (anns == null) return NO_PARAMETER_ANNOTATIONS; ResolvedType[][] result = new ResolvedType[anns.length][]; // CACHING?? - for (int i = 0; i < anns.length; i++) { - if (anns[i] != null) { + for (int i = 0; i < anns.length; i++) + { + if (anns[i] != null) + { result[i] = new ResolvedType[anns[i].length]; - for (int j = 0; j < anns[i].length; j++) { + for (int j = 0; j < anns[i].length; j++) + { result[i][j] = world.resolve(UnresolvedType.forSignature(anns[i][j].getTypeSignature())); } } } return result; - } catch (ClassNotFoundException cnfEx) { + } + catch (ClassNotFoundException cnfEx) + { // just use reflection then } // reflection... AccessibleObject ao = (AccessibleObject) onMember; Annotation[][] anns = null; - if (onMember instanceof Method) { + if (onMember instanceof Method) + { anns = ((Method) ao).getParameterAnnotations(); - } else if (onMember instanceof Constructor) { + } + else if (onMember instanceof Constructor) + { anns = ((Constructor) ao).getParameterAnnotations(); - } else if (onMember instanceof Field) { + } + else if (onMember instanceof Field) + { // anns = null; } if (anns == null) return NO_PARAMETER_ANNOTATIONS; ResolvedType[][] result = new ResolvedType[anns.length][]; // CACHING?? - for (int i = 0; i < anns.length; i++) { - if (anns[i] != null) { + for (int i = 0; i < anns.length; i++) + { + if (anns[i] != null) + { result[i] = new ResolvedType[anns[i].length]; - for (int j = 0; j < anns[i].length; j++) { + for (int j = 0; j < anns[i].length; j++) + { result[i][j] = UnresolvedType.forName(anns[i][j].annotationType().getName()).resolve(world); } }