From 5d5407d0af21c23595e18aaae07eca9866e8f448 Mon Sep 17 00:00:00 2001 From: chiba Date: Sun, 22 Aug 2004 13:04:09 +0000 Subject: [PATCH] fixed a bug in CtClass.getMethods() and javassist.reflect package git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@126 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- src/main/javassist/CtClassType.java | 2 +- src/main/javassist/CtMethod.java | 24 ++++++++--------- src/main/javassist/bytecode/ClassFile.java | 2 +- src/main/javassist/bytecode/Descriptor.java | 15 +++++++++-- .../javassist/reflect/ClassMetaobject.java | 26 +++++++++---------- src/main/javassist/reflect/Reflection.java | 11 ++++++-- 6 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/main/javassist/CtClassType.java b/src/main/javassist/CtClassType.java index fa60df73..cda8fd36 100644 --- a/src/main/javassist/CtClassType.java +++ b/src/main/javassist/CtClassType.java @@ -666,7 +666,7 @@ class CtClassType extends CtClass { CtMethod cm = ((CtClassType)cc).getMethodsCache(); while (cm != null) { if (Modifier.isPublic(cm.getModifiers())) - h.put(cm, cm); + h.put(cm.getStringRep(), cm); cm = cm.next; } diff --git a/src/main/javassist/CtMethod.java b/src/main/javassist/CtMethod.java index f0547150..9d9416b3 100644 --- a/src/main/javassist/CtMethod.java +++ b/src/main/javassist/CtMethod.java @@ -28,12 +28,12 @@ import javassist.bytecode.*; */ public final class CtMethod extends CtBehavior { protected CtMethod next; - protected int cachedHashCode; + protected String cachedStringRep; CtMethod(MethodInfo minfo, CtClass declaring) { super(declaring, minfo); next = null; - cachedHashCode = 0; + cachedStringRep = null; } /** @@ -163,17 +163,17 @@ public final class CtMethod extends CtBehavior { * the hash codes for the two methods are equal. */ public int hashCode() { - /* This method is overridden in ExistingMethod for optimization. - */ - if (cachedHashCode == 0) { - String signature - = methodInfo.getName() + ':' + methodInfo.getDescriptor(); + return getStringRep().hashCode(); + } - // System.identityHashCode() returns 0 only for null. - cachedHashCode = System.identityHashCode(signature.intern()); - } + /* This method is also called by CtClassType.getMethods0(). + */ + final String getStringRep() { + if (cachedStringRep == null) + cachedStringRep = methodInfo.getName() + + Descriptor.getParamDescriptor(methodInfo.getDescriptor()); - return cachedHashCode; + return cachedStringRep; } /** @@ -182,7 +182,7 @@ public final class CtMethod extends CtBehavior { */ public boolean equals(Object obj) { return obj != null && obj instanceof CtMethod - && obj.hashCode() == hashCode(); + && ((CtMethod)obj).getStringRep().equals(getStringRep()); } /** diff --git a/src/main/javassist/bytecode/ClassFile.java b/src/main/javassist/bytecode/ClassFile.java index d9b6dfa6..4f85f667 100644 --- a/src/main/javassist/bytecode/ClassFile.java +++ b/src/main/javassist/bytecode/ClassFile.java @@ -452,7 +452,7 @@ public final class ClassFile { while (it.hasNext()) { MethodInfo minfo = (MethodInfo)it.next(); if (minfo.getName().equals(name) - && Descriptor.eqSignature(minfo.getDescriptor(), descriptor)) + && Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor)) throw new CannotCompileException("duplicate method: " + name); } } diff --git a/src/main/javassist/bytecode/Descriptor.java b/src/main/javassist/bytecode/Descriptor.java index 4a352aaf..54ee506b 100644 --- a/src/main/javassist/bytecode/Descriptor.java +++ b/src/main/javassist/bytecode/Descriptor.java @@ -337,9 +337,11 @@ public class Descriptor { } /** - * Returns true if desc1 and desc2 has the same signature. + * Returns true if the list of the parameter types of desc1 is equal to + * that of desc2. + * For example, "(II)V" and "(II)I" are equal. */ - public static boolean eqSignature(String desc1, String desc2) { + public static boolean eqParamTypes(String desc1, String desc2) { if (desc1.charAt(0) != '(') return false; @@ -353,6 +355,15 @@ public class Descriptor { } } + /** + * Returns the signature of the given descriptor. The signature does + * not include the return type. For example, the signature of "(I)V" + * is "(I)". + */ + public static String getParamDescriptor(String decl) { + return decl.substring(0, decl.indexOf(')') + 1); + } + /** * Returns the CtClass object representing the return * type specified by the given descriptor. diff --git a/src/main/javassist/reflect/ClassMetaobject.java b/src/main/javassist/reflect/ClassMetaobject.java index 000846af..6d43b0e6 100644 --- a/src/main/javassist/reflect/ClassMetaobject.java +++ b/src/main/javassist/reflect/ClassMetaobject.java @@ -249,25 +249,23 @@ public class ClassMetaobject implements Serializable { return methods; Class baseclass = getJavaClass(); - Method[] allmethods = baseclass.getMethods(); + Method[] allmethods = baseclass.getDeclaredMethods(); int n = allmethods.length; methods = new Method[n]; for (int i = 0; i < n; ++i) { Method m = allmethods[i]; - if (m.getDeclaringClass() == baseclass) { - String mname = m.getName(); - if (mname.startsWith(methodPrefix)) { - int k = 0; - for (int j = methodPrefixLen;; ++j) { - char c = mname.charAt(j); - if ('0' <= c && c <= '9') - k = k * 10 + c - '0'; - else - break; - } - - methods[k] = m; + String mname = m.getName(); + if (mname.startsWith(methodPrefix)) { + int k = 0; + for (int j = methodPrefixLen;; ++j) { + char c = mname.charAt(j); + if ('0' <= c && c <= '9') + k = k * 10 + c - '0'; + else + break; } + + methods[k] = m; } } diff --git a/src/main/javassist/reflect/Reflection.java b/src/main/javassist/reflect/Reflection.java index a52351da..014a6152 100644 --- a/src/main/javassist/reflect/Reflection.java +++ b/src/main/javassist/reflect/Reflection.java @@ -24,8 +24,11 @@ import javassist.CtMethod.ConstParameter; *

If a class is reflective, * then all the method invocations on every * instance of that class are intercepted by the runtime - * metaobject controlling that instance. - * To do this, the original class file representing a reflective class: + * metaobject controlling that instance. The methods inherited from the + * super classes are also intercepted except final methods. To intercept + * a final method in a super class, that super class must be also reflective. + * + *

To do this, the original class file representing a reflective class: * *