[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