aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/javassist/util/proxy/ProxyFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/javassist/util/proxy/ProxyFactory.java')
-rw-r--r--src/main/javassist/util/proxy/ProxyFactory.java19
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.
*/