[jboss-cvs] javassist/src/main/javassist/util/proxy ...

Shigeru Chiba chiba at is.titech.ac.jp
Thu Nov 2 01:01:21 EST 2006


  User: chiba   
  Date: 06/11/02 01:01:21

  Modified:    src/main/javassist/util/proxy  ProxyFactory.java
  Log:
  JIRA JASSIST-28 (including a performance bug) has been fixed.
  
  Revision  Changes    Path
  1.18      +131 -11   javassist/src/main/javassist/util/proxy/ProxyFactory.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: ProxyFactory.java
  ===================================================================
  RCS file: /cvsroot/jboss/javassist/src/main/javassist/util/proxy/ProxyFactory.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -b -r1.17 -r1.18
  --- ProxyFactory.java	1 Nov 2006 02:45:05 -0000	1.17
  +++ ProxyFactory.java	2 Nov 2006 06:01:21 -0000	1.18
  @@ -23,9 +23,11 @@
   import java.lang.reflect.Modifier;
   import java.security.ProtectionDomain;
   import java.util.HashMap;
  +import java.util.WeakHashMap;
   import java.util.Iterator;
   import java.util.Map;
   import java.util.Set;
  +import java.lang.ref.WeakReference;
   
   import javassist.CannotCompileException;
   import javassist.bytecode.*;
  @@ -124,6 +126,56 @@
       private static final String HANDLER_SETTER_TYPE = "(" + HANDLER_TYPE + ")V";
   
       /**
  +     * If true, a generated proxy class is cached and it will be reused
  +     * when generating the proxy class with the same properties is requested.
  +     * The default value is true.
  +     *
  +     * @since 3.4
  +     */
  +    public static boolean useCache = true; 
  +
  +    private static WeakHashMap proxyCache = new WeakHashMap();
  +
  +    static class CacheKey {
  +        private String classes;
  +        private MethodFilter filter;
  +        private int hash;
  +        WeakReference proxyClass;
  +
  +        public CacheKey(Class superClass, Class[] interfaces, MethodFilter f) {
  +            classes = getKey(superClass, interfaces);
  +            hash = classes.hashCode();
  +            filter = f;
  +            proxyClass = null;
  +        }
  +
  +        public int hashCode() { return hash; }
  +
  +        public boolean equals(Object obj) {
  +            if (obj instanceof CacheKey) {
  +                CacheKey target = (CacheKey)obj;
  +                return target.filter == filter && target.classes.equals(classes);
  +            }
  +            else
  +                return false;
  +        }
  +
  +        static String getKey(Class superClass, Class[] interfaces) {
  +            StringBuffer sbuf = new StringBuffer();
  +            if (superClass != null)
  +                sbuf.append(superClass.getName());
  +            sbuf.append(':');
  +            if (interfaces != null) {
  +                int len = interfaces.length;
  +                for (int i = 0; i < len; i++)
  +                    sbuf.append(interfaces[i].getName()).append(',');
  +            }
  +
  +            return sbuf.toString();
  +        }
  +    }
  +
  +    /**
        * Constructs a factory of proxy class.
        */
       public ProxyFactory() {
  @@ -174,10 +226,66 @@
        * Generates a proxy class.
        */
       public Class createClass() {
  -        if (thisClass == null)
  +        if (thisClass == null) {
  +            ClassLoader cl = getClassLoader();
  +            if (useCache)
  +                createClass2(cl);
  +            else
  +                createClass3(cl);
  +        }
  +
  +        return thisClass;
  +    }
  +
  +    private void createClass2(ClassLoader cl) {
  +        CacheKey key = new CacheKey(superClass, interfaces, methodFilter);
  +        synchronized (proxyCache) {
  +            HashMap cacheForTheLoader = (HashMap)proxyCache.get(cl);
  +            if (cacheForTheLoader == null) {
  +                cacheForTheLoader = new HashMap();
  +                proxyCache.put(cl, cacheForTheLoader);
  +                cacheForTheLoader.put(key, key);
  +            }
  +            else {
  +                CacheKey found = (CacheKey)cacheForTheLoader.get(key);
  +                if (found == null)
  +                    cacheForTheLoader.put(key, key);
  +                else {
  +                    key = found;
  +                    Class c = isValidEntry(key);    // no need to synchronize
  +                    if (c != null) {
  +                        thisClass = c;
  +                        return;
  +                    }
  +                }
  +            }
  +        }
  +
  +        synchronized (key) {
  +            Class c = isValidEntry(key);
  +            if (c == null) {
  +                createClass3(cl);
  +                key.proxyClass = new WeakReference(thisClass);
  +            }
  +            else
  +                thisClass = c; 
  +        }
  +    }
  +
  +    private Class isValidEntry(CacheKey key) {
  +        WeakReference ref = key.proxyClass;
  +        if (ref != null) {
  +            Class c = (Class)ref.get();
  +            if(c != null && getHandler(c) == handler)
  +                return c;
  +        }
  +
  +        return null;
  +    }
  +
  +    private void createClass3(ClassLoader cl) {
               try {
                   ClassFile cf = make();
  -                ClassLoader cl = getClassLoader();
                   if (writeDirectory != null)
                       FactoryHelper.writeFile(cf, writeDirectory);
   
  @@ -188,7 +296,6 @@
                   throw new RuntimeException(e.getMessage(), e);
               }
   
  -        return thisClass;
       }
   
       /**
  @@ -307,6 +414,19 @@
               }
       }
   
  +    static MethodHandler getHandler(Class clazz) {
  +        try {
  +            Field f = clazz.getField(DEFAULT_INTERCEPTOR);
  +            f.setAccessible(true);
  +            MethodHandler h = (MethodHandler)f.get(null);
  +            f.setAccessible(false);
  +            return h;
  +        }
  +        catch (Exception e) {
  +            throw new RuntimeException(e);
  +        }
  +    }
  +
       private static int counter = 0;
   
       private static synchronized String makeProxyName(String classname) {
  
  
  



More information about the jboss-cvs-commits mailing list