summaryrefslogtreecommitdiffstats
path: root/bcel-builder/src/org
diff options
context:
space:
mode:
authoraclement <aclement>2006-08-08 11:26:28 +0000
committeraclement <aclement>2006-08-08 11:26:28 +0000
commit387c3ac6f23a39aebbc4044093c793009dfea8f6 (patch)
treed1e7d5bfb3796df01bc28fbf6678e70a8026c284 /bcel-builder/src/org
parent4f3c86ded09ce6407d51ab6ca98fac6ed16f8e59 (diff)
downloadaspectj-387c3ac6f23a39aebbc4044093c793009dfea8f6.tar.gz
aspectj-387c3ac6f23a39aebbc4044093c793009dfea8f6.zip
152979: shared cache in the repositorypre_pr_153572
Diffstat (limited to 'bcel-builder/src/org')
-rw-r--r--bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java178
1 files changed, 146 insertions, 32 deletions
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java
index 93c81f20d..1c1f0c359 100644
--- a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java
+++ b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java
@@ -56,6 +56,11 @@ package org.aspectj.apache.bcel.util;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
import java.util.WeakHashMap;
import org.aspectj.apache.bcel.classfile.ClassParser;
@@ -70,86 +75,195 @@ import org.aspectj.apache.bcel.classfile.JavaClass;
*
* @see org.aspectj.apache.bcel.Repository
*
- * @version $Id: ClassLoaderRepository.java,v 1.5 2006/03/10 13:29:05 aclement Exp $
+ * @version $Id: ClassLoaderRepository.java,v 1.6 2006/08/08 11:26:28 aclement Exp $
* @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A>
* @author David Dixon-Peugh
*/
-public class ClassLoaderRepository
- implements Repository
-{
+public class ClassLoaderRepository implements Repository {
private java.lang.ClassLoader loader;
- private WeakHashMap loadedClasses =
- new WeakHashMap(); // CLASSNAME X JAVACLASS
+ private WeakHashMap /*<String classname,JavaClass>*/loadedClassesLocalCache = new WeakHashMap();
+ private static Map /*<URL,JavaClass>*/loadedUrlsSharedCache = new HashMap();
+ public static boolean useSharedCache = true;
+
+ private static long timeManipulatingURLs = 0L;
+ private static long timeSpentLoading = 0L;
+ private static int classesLoadedCount = 0;
+ private static int cacheHitsShared = 0;
+ private static int missSharedEvicted = 0; // Misses in shared cache access due to reference GC
+ private static int misses = 0;
+ private int cacheHitsLocal = 0;
+ private int missLocalEvicted = 0; // Misses in local cache access due to reference GC
+ static {
+ useSharedCache = System.getProperty("org.aspectj.apache.bcel.useSharedCache","true").equalsIgnoreCase("true");
+ }
+
public ClassLoaderRepository( java.lang.ClassLoader loader ) {
this.loader = loader;
}
/**
+ * Store a new JavaClass into this repository as a soft reference and return the reference
+ */
+ private Reference storeClassAsReference( JavaClass clazz ) {
+ Reference ref = new SoftReference(clazz);
+ loadedClassesLocalCache.put( clazz.getClassName(), ref);
+ clazz.setRepository( this );
+ return ref;
+ }
+
+ /**
+ * Store a reference in the shared cache
+ */
+ private void storeReferenceShared(URL url, Reference ref) {
+ if (useSharedCache) loadedUrlsSharedCache.put(url, ref);
+ }
+
+ /**
* Store a new JavaClass into this Repository.
*/
public void storeClass( JavaClass clazz ) {
- loadedClasses.put( clazz.getClassName(),
- clazz );
- clazz.setRepository( this );
+ storeClassAsReference(clazz);
}
/**
* Remove class from repository
*/
public void removeClass(JavaClass clazz) {
- loadedClasses.remove(clazz.getClassName());
+ loadedClassesLocalCache.remove(clazz.getClassName());
}
/**
- * Find an already defined JavaClass.
+ * Find an already defined JavaClass in the local cache.
*/
public JavaClass findClass( String className ) {
- if ( loadedClasses.containsKey( className )) {
- return (JavaClass) loadedClasses.get( className );
- } else {
- return null;
+ Object o = loadedClassesLocalCache.get( className );
+ if (o != null) {
+ o = ((Reference)o).get();
+ if (o != null) {
+ return (JavaClass)o;
+ } else {
+ missLocalEvicted++;
+ }
}
+ return null;
+ }
+
+ /**
+ * Find an already defined JavaClass in the shared cache.
+ */
+ private JavaClass findClassShared(URL url) {
+ if (!useSharedCache) return null;
+ Object o = (Reference)loadedUrlsSharedCache.get(url);
+ if (o != null) {
+ o = ((Reference)o).get();
+ if (o != null) {
+ return (JavaClass)o;
+ } else {
+ missSharedEvicted++;
+ }
+ }
+ return null;
}
+
/**
* Lookup a JavaClass object from the Class Name provided.
*/
- public JavaClass loadClass( String className )
- throws ClassNotFoundException
- {
+ public JavaClass loadClass( String className ) throws ClassNotFoundException {
String classFile = className.replace('.', '/');
- JavaClass RC = findClass( className );
- if (RC != null) { return RC; }
+ // Check the local cache
+ JavaClass clazz = findClass(className);
+ if (clazz != null) { cacheHitsLocal++; return clazz; }
try {
- InputStream is =
- loader.getResourceAsStream( classFile + ".class" );
+ // Work out the URL
+ long time = System.currentTimeMillis();
+ java.net.URL url = (useSharedCache?loader.getResource( classFile + ".class" ):null);
+ if (useSharedCache && url==null) throw new ClassNotFoundException(className + " not found.");
+ InputStream is = (useSharedCache?url.openStream():loader.getResourceAsStream( classFile + ".class" ));
+ timeManipulatingURLs += (System.currentTimeMillis() - time);
+
+ // Check the shared cache
+ clazz = findClassShared(url);
+ if (clazz != null) { cacheHitsShared++; timeSpentLoading+=(System.currentTimeMillis() - time); return clazz; }
+
+ // Didn't find it in either cache
+ misses++;
- if(is == null) {
- throw new ClassNotFoundException(className + " not found.");
- }
+ if (is == null) { // TODO move this up?
+ throw new ClassNotFoundException(className + " not found.");
+ }
- ClassParser parser = new ClassParser( is, className );
- RC = parser.parse();
+ ClassParser parser = new ClassParser( is, className );
+ clazz = parser.parse();
- storeClass( RC );
+ // Store it in both caches
+ Reference ref = storeClassAsReference( clazz );
+ storeReferenceShared(url,ref);
- return RC;
+ timeSpentLoading += (System.currentTimeMillis() - time);
+ classesLoadedCount++;
+ return clazz;
} catch (IOException e) {
throw new ClassNotFoundException( e.toString() );
}
}
+
+/**
+ * Produce a report on cache usage.
+ */
+ public String reportAllStatistics() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("BCEL repository report.");
+ if (!useSharedCache) sb.append(" (Shared cache deactivated)");
+ sb.append(" Total time spent loading: "+timeSpentLoading+"ms.");
+ sb.append(" Time manipulating URLs: "+timeManipulatingURLs+"ms.");
+ sb.append(" Classes loaded: "+classesLoadedCount+".");
+ if (useSharedCache) sb.append(" URL cache (hits/missDueToEviction): ("+cacheHitsShared+"/"+missSharedEvicted+").");
+ sb.append(" Local cache (hits/missDueToEviction): ("+cacheHitsLocal+"/"+missLocalEvicted+").");
+ return sb.toString();
+ }
+
+ public int reportLocalCacheHits() {
+ return cacheHitsLocal;
+ }
+
+ public static int reportSharedCacheHits() {
+ return cacheHitsShared;
+ }
+
+ /**
+ * Reset statistics and clear all caches
+ */
+ public void reset() {
+ timeManipulatingURLs = 0L;
+ timeSpentLoading = 0L;
+ classesLoadedCount = 0;
+ cacheHitsLocal = 0;
+ cacheHitsShared = 0;
+ missSharedEvicted = 0;
+ missLocalEvicted = 0;
+ misses = 0;
+ clear();
+ clearShared();
+ }
+
+
public JavaClass loadClass(Class clazz) throws ClassNotFoundException {
return loadClass(clazz.getName());
}
- /** Clear all entries from cache.
- */
+ /** Clear all entries from the local cache */
public void clear() {
- loadedClasses.clear();
+ loadedClassesLocalCache.clear();
+ }
+
+ /** Clear all entries from the shared cache */
+ public static void clearShared() {
+ loadedUrlsSharedCache.clear();
}
}