diff options
author | Stefan Starke <stefan@starkeweb.org> | 2019-10-08 13:27:41 +0200 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2022-01-13 15:07:30 -0800 |
commit | 0e58847d8d341b70734576aa813f755d9a716a18 (patch) | |
tree | 393edd496668ea365780412d10b40e94ee7ac963 /weaver | |
parent | 1b3cead1715cd4f233d81c88ba7a33dc1aa59886 (diff) | |
download | aspectj-0e58847d8d341b70734576aa813f755d9a716a18.tar.gz aspectj-0e58847d8d341b70734576aa813f755d9a716a18.zip |
Optimize class loading
In our project we found out that during the build up of the spring context
the class loading takes a very long time.
Root cause is the huge amount of file I/O during pointcut class loading.
We are taking about ~250k file loads.
With these changes we managed to cut down the starting time by around 50%.
What we found out is that IMHO - the clear method of the ClassLoaderRepository
is called far too often -> in our settings this resulted in not a single cache
hit as the cache got cleared permanently.
Therefore we de-actived the cache clear calls inside the ClassLoaderRepository.
Secondly we changed the Java15AnnotationFinder in a way to not always create
new objects for the ClassLoaderRepository but re-use one static instance.
Otherwise we experienced >100k objects being created.
Last but not least we introduced a cache for unavailable classes so that
they do not have to be looked up using file I/O over and over again.
The whole behavior is configurable via
+ org.aspectj.apache.bcel.useSingleRepositoryInstance (default: true)
+ org.aspectj.apache.bcel.useUnavailableClassesCache (default: true)
+ org.aspectj.apache.bcel.ignoreCacheClearRequests (default: true)
Signed-off-by: Stefan Starke <stefan@starkeweb.org>
Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>
Diffstat (limited to 'weaver')
-rw-r--r-- | weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java | 53 |
1 files changed, 39 insertions, 14 deletions
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 dfddd18da..ef437b724 100644 --- a/weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java +++ b/weaver/src/main/java/org/aspectj/weaver/reflect/Java15AnnotationFinder.java @@ -42,9 +42,17 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { private Repository bcelRepository; private BcelWeakClassLoaderReference classLoaderRef; + + private static Repository staticBcelRepository; + private static BcelWeakClassLoaderReference staticClassLoaderRef; + private World world; private static boolean useCachingClassLoaderRepository; + //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"); @@ -58,14 +66,31 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { } public void setClassLoader(ClassLoader aLoader) { - this.classLoaderRef = new BcelWeakClassLoaderReference(aLoader); + //Set class loader ref + if (useSingleInstances && staticClassLoaderRef == null) + staticClassLoaderRef = new BcelWeakClassLoaderReference(aLoader); + else + this.classLoaderRef = new BcelWeakClassLoaderReference(aLoader); + + //Set repository if (useCachingClassLoaderRepository) { - this.bcelRepository = new ClassLoaderRepository(classLoaderRef); - } else { - this.bcelRepository = new NonCachingClassLoaderRepository(classLoaderRef); + 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()); } } + private Repository getBcelRepository() { + return useSingleInstances ? staticBcelRepository : bcelRepository; + } + public void setWorld(World aWorld) { this.world = aWorld; } @@ -112,7 +137,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { } private ClassLoader getClassLoader() { - return classLoaderRef.getClassLoader(); + return useSingleInstances ? staticClassLoaderRef.getClassLoader() : classLoaderRef.getClassLoader(); } public AnnotationAJ getAnnotationOfType(UnresolvedType ofType, Member onMember) { @@ -145,7 +170,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { 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 = AnnotationGen.NO_ANNOTATIONS; @@ -164,7 +189,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { public String getAnnotationDefaultValue(Member onMember) { try { - JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass()); + JavaClass jc = getBcelRepository().loadClass(onMember.getDeclaringClass()); if (onMember instanceof Method) { org.aspectj.apache.bcel.classfile.Method bcelMethod = jc.getMethod((Method) onMember); @@ -200,7 +225,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { // we can just use reflection. if (!areRuntimeAnnotationsSufficient) { try { - JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass()); + JavaClass jc = getBcelRepository().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); @@ -215,7 +240,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { anns = bcelField.getAnnotations(); } // the answer is cached and we don't want to hold on to memory - bcelRepository.clear(); + getBcelRepository().clear(); if (anns == null || anns.length == 0) { return ResolvedType.NONE; } @@ -246,9 +271,9 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { // 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); + JavaClass jc = getBcelRepository().loadClass(forClass); org.aspectj.apache.bcel.classfile.annotation.AnnotationGen[] anns = jc.getAnnotations(); - bcelRepository.clear(); + getBcelRepository().clear(); if (anns == null) { return ResolvedType.NONE; } else { @@ -276,7 +301,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { return null; try { - JavaClass jc = bcelRepository.loadClass(forMember.getDeclaringClass()); + JavaClass jc = getBcelRepository().loadClass(forMember.getDeclaringClass()); LocalVariableTable lvt = null; int numVars = 0; if (forMember instanceof Method) { @@ -320,7 +345,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { // don't hog // memory. try { - JavaClass jc = bcelRepository.loadClass(onMember.getDeclaringClass()); + JavaClass jc = getBcelRepository().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); @@ -340,7 +365,7 @@ public class Java15AnnotationFinder implements AnnotationFinder, ArgNameFinder { // 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][]; |