From 8dac8e2ce448d7f1d79e1fe9de71b551d62b0a63 Mon Sep 17 00:00:00 2001 From: chiba Date: Thu, 19 Jul 2007 10:21:26 +0000 Subject: [PATCH] modified redirectMethodCall() in CodeConverter git-svn-id: http://anonsvn.jboss.org/repos/javassist/trunk@397 30ef5769-5b8d-40dd-aea6-55b5d6557bb3 --- src/main/javassist/bytecode/ConstPool.java | 58 ++++++++++++++++++- src/main/javassist/convert/TransformCall.java | 41 +++++++++++-- 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/main/javassist/bytecode/ConstPool.java b/src/main/javassist/bytecode/ConstPool.java index 2b2348e8..7ac8dc2f 100644 --- a/src/main/javassist/bytecode/ConstPool.java +++ b/src/main/javassist/bytecode/ConstPool.java @@ -205,6 +205,34 @@ public final class ConstPool { return ntinfo.typeDescriptor; } + /** + * Reads the class_index field of the + * CONSTANT_Fieldref_info, + * CONSTANT_Methodref_info, + * or CONSTANT_Interfaceref_info, + * structure at the given index. + * + * @since 3.6 + */ + public int getMemberClass(int index) { + MemberrefInfo minfo = (MemberrefInfo)getItem(index); + return minfo.classIndex; + } + + /** + * Reads the name_and_type_index field of the + * CONSTANT_Fieldref_info, + * CONSTANT_Methodref_info, + * or CONSTANT_Interfaceref_info, + * structure at the given index. + * + * @since 3.6 + */ + public int getMemberNameAndType(int index) { + MemberrefInfo minfo = (MemberrefInfo)getItem(index); + return minfo.nameAndTypeIndex; + } + /** * Reads the class_index field of the * CONSTANT_Fieldref_info structure @@ -274,7 +302,7 @@ public final class ConstPool { if (f == null) return null; else { - NameAndTypeInfo n = (NameAndTypeInfo) getItem(f.nameAndTypeIndex); + NameAndTypeInfo n = (NameAndTypeInfo)getItem(f.nameAndTypeIndex); if(n == null) return null; else @@ -579,6 +607,34 @@ public final class ConstPool { return 0; // false } + /** + * Determines whether CONSTANT_Methodref_info, + * CONSTANT_Fieldref_info, or + * CONSTANT_InterfaceMethodref_info structure + * at the given index has the name and the descriptor + * given as the arguments. + * + * @param membername the member name + * @param desc the descriptor of the member. + * @param index the index into the constant pool table + * + * @return the name of the target class specified by + * the ..._info structure + * at index. + * Otherwise, null if that structure does not + * match the given member name and descriptor. + */ + public String eqMember(String membername, String desc, int index) { + MemberrefInfo minfo = (MemberrefInfo)getItem(index); + NameAndTypeInfo ntinfo + = (NameAndTypeInfo)getItem(minfo.nameAndTypeIndex); + if (getUtf8Info(ntinfo.memberName).equals(membername) + && getUtf8Info(ntinfo.typeDescriptor).equals(desc)) + return getClassInfo(minfo.classIndex); + else + return null; // false + } + private int addItem(ConstInfo info) { items.addElement(info); return numOfItems++; diff --git a/src/main/javassist/convert/TransformCall.java b/src/main/javassist/convert/TransformCall.java index bfa81cb3..fb8395ee 100644 --- a/src/main/javassist/convert/TransformCall.java +++ b/src/main/javassist/convert/TransformCall.java @@ -17,7 +17,9 @@ package javassist.convert; import javassist.CtClass; import javassist.CtMethod; +import javassist.ClassPool; import javassist.Modifier; +import javassist.NotFoundException; import javassist.bytecode.*; public class TransformCall extends Transformer { @@ -55,7 +57,10 @@ public class TransformCall extends Transformer { /** * Modify INVOKEINTERFACE, INVOKESPECIAL, INVOKESTATIC and INVOKEVIRTUAL - * so that a different method is invoked. + * so that a different method is invoked. The class name in the operand + * of these instructions might be a subclass of the target class specified + * by classname. This method transforms the instruction + * in that case unless the subclass overrides the target method. */ public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode @@ -64,15 +69,41 @@ public class TransformCall extends Transformer { if (c == INVOKEINTERFACE || c == INVOKESPECIAL || c == INVOKESTATIC || c == INVOKEVIRTUAL) { int index = iterator.u16bitAt(pos + 1); - int typedesc = cp.isMember(classname, methodname, index); - if (typedesc != 0) - if (cp.getUtf8Info(typedesc).equals(methodDescriptor)) - pos = match(c, pos, iterator, typedesc, cp); + String cname = cp.eqMember(methodname, methodDescriptor, index); + if (cname != null && matchClass(cname, clazz.getClassPool())) { + int ntinfo = cp.getMemberNameAndType(index); + pos = match(c, pos, iterator, + cp.getNameAndTypeDescriptor(ntinfo), cp); + } } return pos; } + private boolean matchClass(String name, ClassPool pool) { + if (classname.equals(name)) + return true; + + try { + CtClass clazz = pool.get(name); + CtClass declClazz = pool.get(classname); + if (clazz.subtypeOf(declClazz)) + try { + CtMethod m = clazz.getMethod(methodname, methodDescriptor); + return m.getDeclaringClass().getName().equals(classname); + } + catch (NotFoundException e) { + // maybe the original method has been removed. + return true; + } + } + catch (NotFoundException e) { + return false; + } + + return false; + } + protected int match(int c, int pos, CodeIterator iterator, int typedesc, ConstPool cp) throws BadBytecode { -- 2.39.5