From c04c375e813597eaeb305a641f58a89fe665ea54 Mon Sep 17 00:00:00 2001 From: shifujun Date: Fri, 8 Dec 2023 14:48:28 +0800 Subject: [PATCH] Fix MemberResolver.lookupMethod bug when super class has more precise match When onlyExact=false and super class have a more precise match, it should not return with current class's maybe result. New added testSuperCall reveals the problem. --- .../javassist/compiler/MemberResolver.java | 25 +++++++----- src/test/javassist/JvstTest5.java | 25 +++++++++++- src/test/javassist/SuperCallCase.java | 38 +++++++++++++++++++ 3 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 src/test/javassist/SuperCallCase.java diff --git a/src/main/javassist/compiler/MemberResolver.java b/src/main/javassist/compiler/MemberResolver.java index c01974df..dd271368 100644 --- a/src/main/javassist/compiler/MemberResolver.java +++ b/src/main/javassist/compiler/MemberResolver.java @@ -130,9 +130,7 @@ public class MemberResolver implements TokenId { if (onlyExact) maybe = null; - else - if (maybe != null) - return maybe; + //else maybe super class has more precise match int mod = clazz.getModifiers(); boolean isIntf = Modifier.isInterface(mod); @@ -143,8 +141,11 @@ public class MemberResolver implements TokenId { if (pclazz != null) { Method r = lookupMethod(pclazz, methodName, argTypes, argDims, argClassNames, onlyExact); - if (r != null) - return r; + if (r != null) { + if (maybe == null || maybe.notmatch > r.notmatch) { + maybe = r; + } + } } } } @@ -156,8 +157,11 @@ public class MemberResolver implements TokenId { Method r = lookupMethod(intf, methodName, argTypes, argDims, argClassNames, onlyExact); - if (r != null) - return r; + if (r != null) { + if (maybe == null || maybe.notmatch > r.notmatch) { + maybe = r; + } + } } if (isIntf) { @@ -166,8 +170,11 @@ public class MemberResolver implements TokenId { if (pclazz != null) { Method r = lookupMethod(pclazz, methodName, argTypes, argDims, argClassNames, onlyExact); - if (r != null) - return r; + if (r != null) { + if (maybe == null || maybe.notmatch > r.notmatch) { + maybe = r; + } + } } } } diff --git a/src/test/javassist/JvstTest5.java b/src/test/javassist/JvstTest5.java index f1c56837..561181c3 100644 --- a/src/test/javassist/JvstTest5.java +++ b/src/test/javassist/JvstTest5.java @@ -4,6 +4,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.lang.reflect.TypeVariable; import javassist.bytecode.AccessFlag; @@ -166,7 +167,7 @@ public class JvstTest5 extends JvstTestRoot { CtClass cc = sloader.makeClass("test5.JIRA256"); ClassFile ccFile = cc.getClassFile(); ConstPool constpool = ccFile.getConstPool(); - + AnnotationsAttribute attr = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag); javassist.bytecode.annotation.Annotation entityAnno = new javassist.bytecode.annotation.Annotation("test5.Entity", constpool); @@ -181,7 +182,7 @@ public class JvstTest5 extends JvstTestRoot { assertTrue(o.getClass().getName().equals("test5.JIRA256")); java.lang.annotation.Annotation[] annotations = o.getClass().getDeclaredAnnotations(); - assertEquals(1, annotations.length); + assertEquals(1, annotations.length); } public void testJIRA250() throws Exception { @@ -625,4 +626,24 @@ public class JvstTest5 extends JvstTestRoot { assertEquals(1, attr.size()); assertNull(attr.parameterName(0)); } + + public void testSuperCall() throws Exception { + String javacResult = new BearKeeper().javacResult(); + assertEquals("Man feed(Bear)", javacResult); + + CtClass cc = sloader.get("javassist.BearKeeper"); + CtMethod cm = CtMethod.make( + "public String javassistResult() {return super.feed(new javassist.Bear());}", + cc); + cc.addMethod(cm); + cc.setModifiers(Modifier.PUBLIC); + cc.writeFile(); + Object obj = make(cc.getName()); + Method m = obj.getClass().getMethod("javassistResult"); + Object javassistResult = m.invoke(obj); + + //before this fix + //expected: but was: + assertEquals(javacResult, javassistResult); + } } diff --git a/src/test/javassist/SuperCallCase.java b/src/test/javassist/SuperCallCase.java new file mode 100644 index 00000000..8d5ea9e7 --- /dev/null +++ b/src/test/javassist/SuperCallCase.java @@ -0,0 +1,38 @@ +package javassist; + +class Animal { +} + +class Bear extends Animal { +} + + +/** + * Base class has a method with precise type. + */ +class Man { + String feed(Bear bear) { + return "Man feed(Bear)"; + } +} + +/** + * Derived class has a method which has same name with base class's and more imprecise type. + */ +class Keeper extends Man { + String feed(Animal animal) { + return "Keeper feed(Animal)"; + } +} + +/** + * Derived class has a method which call super method with precise type. + */ +class BearKeeper extends Keeper { + public BearKeeper() { + } + + String javacResult() { + return super.feed(new Bear()); + } +} -- 2.39.5