git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@126 30ef5769-5b8d-40dd-aea6-55b5d6557bb3tags/rel_3_17_1_ga
@@ -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; | |||
} |
@@ -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()); | |||
} | |||
/** |
@@ -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); | |||
} | |||
} |
@@ -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 <code>CtClass</code> object representing the return | |||
* type specified by the given descriptor. |
@@ -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; | |||
} | |||
} | |||
@@ -24,8 +24,11 @@ import javassist.CtMethod.ConstParameter; | |||
* <p>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. | |||
* | |||
* <p>To do this, the original class file representing a reflective class: | |||
* | |||
* <ul><pre> | |||
* class Person { | |||
@@ -298,6 +301,10 @@ public class Reflection implements Translator { | |||
return; | |||
m2 = m; | |||
if (Modifier.isFinal(mod)) { | |||
mod &= ~Modifier.FINAL; | |||
m2.setModifiers(mod); | |||
} | |||
} | |||
else { | |||
if (Modifier.isFinal(mod)) |