[jboss-cvs] JBossAS SVN: r61752 - in projects/aop/trunk/aop/src: test/org/jboss/test/aop/methodhashing and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Mar 27 12:03:50 EDT 2007
Author: kabir.khan at jboss.com
Date: 2007-03-27 12:03:50 -0400 (Tue, 27 Mar 2007)
New Revision: 61752
Modified:
projects/aop/trunk/aop/src/main/org/jboss/aop/util/MethodHashing.java
projects/aop/trunk/aop/src/test/org/jboss/test/aop/methodhashing/MethodHashingTestCase.java
Log:
Optimize MethodHashing so we don't calculate the hash every time we call findMethodByHash
Modified: projects/aop/trunk/aop/src/main/org/jboss/aop/util/MethodHashing.java
===================================================================
--- projects/aop/trunk/aop/src/main/org/jboss/aop/util/MethodHashing.java 2007-03-27 16:02:50 UTC (rev 61751)
+++ projects/aop/trunk/aop/src/main/org/jboss/aop/util/MethodHashing.java 2007-03-27 16:03:50 UTC (rev 61752)
@@ -31,6 +31,9 @@
import java.util.Map;
import java.util.WeakHashMap;
+import org.jboss.aop.util.reference.MethodPersistentReference;
+import org.jboss.aop.util.reference.PersistentReference;
+
/**
* Create a unique hash for
*
@@ -44,12 +47,20 @@
// Static --------------------------------------------------------
static Map hashMap = new WeakHashMap();
+ static Map methodHashesByClass = new WeakHashMap();
+
public static Method findMethodByHash(Class clazz, long hash) throws Exception
{
- Method[] methods = SecurityActions.getDeclaredMethods(clazz);
- for (int i = 0; i < methods.length; i++)
+ return findMethodByHash(clazz, new Long(hash));
+ }
+
+ public static Method findMethodByHash(Class clazz, Long hash) throws Exception
+ {
+ Map hashes = getMethodHashes(clazz);
+ MethodPersistentReference ref = (MethodPersistentReference)hashes.get(hash);
+ if (ref != null)
{
- if (methodHash(methods[i]) == hash) return methods[i];
+ return ref.getMethod();
}
if (clazz.isInterface())
@@ -71,7 +82,7 @@
}
return null;
}
-
+
public static Constructor findConstructorByHash(Class clazz, long hash) throws Exception
{
Constructor[] cons = SecurityActions.getDeclaredConstructors(clazz);
@@ -90,13 +101,13 @@
throws Exception
{
Class[] parameterTypes = method.getParameterTypes();
- String methodDesc = method.getName()+"(";
+ StringBuffer methodDesc = new StringBuffer(method.getName()+"(");
for(int j = 0; j < parameterTypes.length; j++)
{
- methodDesc += getTypeString(parameterTypes[j]);
+ methodDesc.append(getTypeString(parameterTypes[j]));
}
- methodDesc += ")"+getTypeString(method.getReturnType());
- return createHash(methodDesc);
+ methodDesc.append(")"+getTypeString(method.getReturnType()));
+ return createHash(methodDesc.toString());
}
public static long createHash(String methodDesc)
@@ -119,52 +130,16 @@
throws Exception
{
Class[] parameterTypes = method.getParameterTypes();
- String methodDesc = method.getName()+"(";
+ StringBuffer methodDesc = new StringBuffer(method.getName()+"(");
for(int j = 0; j < parameterTypes.length; j++)
{
- methodDesc += getTypeString(parameterTypes[j]);
+ methodDesc.append(getTypeString(parameterTypes[j]));
}
- methodDesc += ")";
-
- long hash = 0;
- ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream(512);
- MessageDigest messagedigest = MessageDigest.getInstance("SHA");
- DataOutputStream dataoutputstream = new DataOutputStream(new DigestOutputStream(bytearrayoutputstream, messagedigest));
- dataoutputstream.writeUTF(methodDesc);
- dataoutputstream.flush();
- byte abyte0[] = messagedigest.digest();
- for(int j = 0; j < Math.min(8, abyte0.length); j++)
- hash += (long)(abyte0[j] & 0xff) << j * 8;
- return hash;
+ methodDesc.append(")");
+
+ return createHash(methodDesc.toString());
}
- /**
- * Calculate method hashes. This algo is taken from RMI.
- *
- * @param intf
- * @return
- */
- public static Map getInterfaceHashes(Class intf)
- {
- // Create method hashes
- Method[] methods = SecurityActions.getDeclaredMethods(intf);
- HashMap map = new HashMap();
- for (int i = 0; i < methods.length; i++)
- {
- Method method = methods[i];
- try
- {
- long hash = methodHash(method);
- map.put(method.toString(), new Long(hash));
- }
- catch (Exception e)
- {
- }
- }
-
- return map;
- }
-
static String getTypeString(Class cl)
{
if (cl == Byte.TYPE)
@@ -228,4 +203,65 @@
return ((Long)methodHashes.get(method.toString())).longValue();
}
+
+ /**
+ * Calculate method hashes. This algo is taken from RMI.
+ *
+ * @param intf
+ * @return
+ * @deprecated I can't see why this would have any value to anybody apart from this class. It will be made private
+ */
+ public static Map getInterfaceHashes(Class intf)
+ {
+ // Create method hashes
+ Method[] methods = SecurityActions.getDeclaredMethods(intf);
+ HashMap map = new HashMap();
+ for (int i = 0; i < methods.length; i++)
+ {
+ Method method = methods[i];
+ try
+ {
+ long hash = methodHash(method);
+ map.put(method.toString(), new Long(hash));
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ return map;
+ }
+
+ private static Map getMethodHashes(Class clazz)
+ {
+ Map methodHashes = (Map)methodHashesByClass.get(clazz);
+ if (methodHashes == null)
+ {
+ methodHashes = getMethodHashMap(clazz);
+ methodHashesByClass.put(clazz, methodHashes);
+ }
+ return methodHashes;
+ }
+
+ private static Map getMethodHashMap(Class clazz)
+ {
+ // Create method hashes
+ Method[] methods = SecurityActions.getDeclaredMethods(clazz);
+ HashMap map = new HashMap();
+ for (int i = 0; i < methods.length; i++)
+ {
+ Method method = methods[i];
+ try
+ {
+ long hash = methodHash(method);
+ //Use Clebert's Persistent References so we don't get memory leaks
+ map.put(new Long(hash), new MethodPersistentReference(methods[i], PersistentReference.REFERENCE_SOFT));
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ return map;
+ }
}
Modified: projects/aop/trunk/aop/src/test/org/jboss/test/aop/methodhashing/MethodHashingTestCase.java
===================================================================
--- projects/aop/trunk/aop/src/test/org/jboss/test/aop/methodhashing/MethodHashingTestCase.java 2007-03-27 16:02:50 UTC (rev 61751)
+++ projects/aop/trunk/aop/src/test/org/jboss/test/aop/methodhashing/MethodHashingTestCase.java 2007-03-27 16:03:50 UTC (rev 61752)
@@ -21,6 +21,7 @@
*/
package org.jboss.test.aop.methodhashing;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Map;
@@ -55,6 +56,8 @@
super(arg0);
}
+
+
public void testDeclaredMethodHashing() throws Exception
{
Class clazz = SubClass.class;
@@ -184,4 +187,59 @@
assertEquals(methodInfo.getParameterTypes().length, method.getParameterTypes().length);
}
+ /**
+ * Written as a sanity check when optimizing the MethodHashing class
+ */
+ public void testMethodHashingFunctionality() throws Exception
+ {
+ Method test1 = TestSubClass.class.getDeclaredMethod("test1", new Class[] {String.class});
+ Method test2 = TestSubClass.class.getDeclaredMethod("test2", new Class[] {String.class, Integer.TYPE});
+ long test1Hash = MethodHashing.calculateHash(test1);
+ long test2Hash = MethodHashing.calculateHash(test2);
+ assertEquals(-129615495583814694L, test1Hash);
+ assertEquals(-1228234556488761696l, test2Hash);
+
+ assertEquals(test1Hash, MethodHashing.methodHash(test1));
+ assertEquals(test2Hash, MethodHashing.methodHash(test2));
+
+ assertEquals(test1, MethodHashing.findMethodByHash(TestSubClass.class, test1Hash));
+ assertEquals(test2, MethodHashing.findMethodByHash(TestSubClass.class, test2Hash));
+
+ //This method seems pointless and stupid, but better test it anyway for backwards compatibility
+ Map hashes = MethodHashing.getInterfaceHashes(TestSubClass.class);
+ assertEquals(2, hashes.size());
+ long h1 = ((Long)hashes.get(test1.toString())).longValue();
+ assertEquals(test1Hash, h1);
+ long h2 = ((Long)hashes.get(test2.toString())).longValue();
+ assertEquals(test2Hash, h2);
+
+ Constructor ctor1 = TestSubClass.class.getDeclaredConstructor(new Class[0]);
+ Constructor ctor2 = TestSubClass.class.getDeclaredConstructor(new Class[] {Integer.TYPE});
+ long con1Hash = MethodHashing.constructorHash(ctor1);
+ long con2Hash = MethodHashing.constructorHash(ctor2);
+ assertEquals(-6451128523270287660L, con1Hash);
+ assertEquals(-4215863789501864959L, con2Hash);
+
+ assertEquals(ctor1, MethodHashing.findConstructorByHash(TestSubClass.class, con1Hash));
+ assertEquals(ctor2, MethodHashing.findConstructorByHash(TestSubClass.class, con2Hash));
+
+ }
+
+ static class TestBaseClass
+ {
+ TestBaseClass(){}
+ TestBaseClass(int i){}
+ void test3() {}
+ }
+
+ static class TestSubClass extends TestBaseClass
+ {
+ TestSubClass() {}
+
+ TestSubClass(int i){super(i);}
+
+ void test1(String s) {}
+
+ int test2(String s, int i) {return i;}
+ }
}
More information about the jboss-cvs-commits
mailing list