diff options
author | chibash <chiba@javassist.org> | 2016-07-30 18:47:59 +0900 |
---|---|---|
committer | chibash <chiba@javassist.org> | 2016-07-30 18:47:59 +0900 |
commit | e1ae09e50449726da3564486b21b59f2fe1b6d16 (patch) | |
tree | 1736ac5841f15ecae0fe18448a40508bc3ce90a5 /src/main/javassist/util | |
parent | 13c7057570305ca3b6d3890ec3f509f487c6973a (diff) | |
download | javassist-e1ae09e50449726da3564486b21b59f2fe1b6d16.tar.gz javassist-e1ae09e50449726da3564486b21b59f2fe1b6d16.zip |
fixes a bug of ProxyFactory. It could not deal with default methods declared in an interface.
Diffstat (limited to 'src/main/javassist/util')
-rw-r--r-- | src/main/javassist/util/proxy/ProxyFactory.java | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/src/main/javassist/util/proxy/ProxyFactory.java b/src/main/javassist/util/proxy/ProxyFactory.java index 26c5c6c9..a85e8de0 100644 --- a/src/main/javassist/util/proxy/ProxyFactory.java +++ b/src/main/javassist/util/proxy/ProxyFactory.java @@ -1230,7 +1230,7 @@ public class ProxyFactory { return minfo; } - private static MethodInfo makeDelegator(Method meth, String desc, + private MethodInfo makeDelegator(Method meth, String desc, ConstPool cp, Class declClass, String delegatorName) { MethodInfo delegator = new MethodInfo(cp, delegatorName, desc); delegator.setAccessFlags(Modifier.FINAL | Modifier.PUBLIC @@ -1243,7 +1243,8 @@ public class ProxyFactory { Bytecode code = new Bytecode(cp, 0, 0); code.addAload(0); int s = addLoadParameters(code, meth.getParameterTypes(), 1); - code.addInvokespecial(declClass.isInterface(), cp.addClassInfo(declClass.getName()), + Class targetClass = invokespecialTarget(declClass); + code.addInvokespecial(targetClass.isInterface(), cp.addClassInfo(targetClass.getName()), meth.getName(), desc); addReturn(code, meth.getReturnType()); code.setMaxLocals(++s); @@ -1251,6 +1252,20 @@ public class ProxyFactory { return delegator; } + /* Suppose that the receiver type is S, the invoked method + * is declared in T, and U is the immediate super class of S + * (or its interface). If S <: U <: T (S <: T reads "S extends T"), + * the target type of invokespecial has to be not T but U. + */ + private Class invokespecialTarget(Class declClass) { + if (declClass.isInterface()) + for (Class i: interfaces) + if (declClass.isAssignableFrom(i)) + return i; + + return superClass; + } + /** * @param delegatorName null if the original method is abstract. */ |