* @see Descriptor#ofConstructor(CtClass[])
*/
public void addInvokespecial(boolean isInterface, int clazz, String name, String desc) {
- add(INVOKESPECIAL);
int index;
if (isInterface)
index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
else
index = constPool.addMethodrefInfo(clazz, name, desc);
+ addInvokespecial(index, desc);
+ }
+
+ /**
+ * Appends INVOKESPECIAL.
+ *
+ * @param index the index of <code>CONSTANT_Methodref_info</code>
+ * or <code>CONSTANT_InterfaceMethodref_info</code>
+ * @param desc the descriptor of the method signature.
+ *
+ * @see Descriptor#ofMethod(CtClass,CtClass[])
+ * @see Descriptor#ofConstructor(CtClass[])
+ */
+ public void addInvokespecial(int index, String desc) {
+ add(INVOKESPECIAL);
addIndex(index);
growStack(Descriptor.dataSize(desc) - 1);
}
* @param methodname the method name.
* @param descriptor the method descriptor.
*/
- public void recordSpecialProceed(String target, String classname,
- String methodname, String descriptor)
+ public void recordSpecialProceed(String target, final String classname,
+ final String methodname, final String descriptor,
+ final int methodIndex)
throws CompileError
{
Parser p = new Parser(new Lex(target));
final ASTree texpr = p.parseExpression(stable);
- final String cname = classname;
- final String method = methodname;
- final String desc = descriptor;
ProceedHandler h = new ProceedHandler() {
public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
throws CompileError
{
- gen.compileInvokeSpecial(texpr, cname, method, desc, args);
+ gen.compileInvokeSpecial(texpr, methodIndex, descriptor, args);
}
public void setReturnType(JvstTypeChecker c, ASTList args)
throws CompileError
{
- c.compileInvokeSpecial(texpr, cname, method, desc, args);
+ c.compileInvokeSpecial(texpr, classname, methodname, descriptor, args);
}
};
/* called by Javac#recordSpecialProceed().
*/
- void compileInvokeSpecial(ASTree target, String classname,
- String methodname, String descriptor,
- ASTList args)
+ void compileInvokeSpecial(ASTree target, int methodIndex,
+ String descriptor, ASTList args)
throws CompileError
{
target.accept(this);
int nargs = getMethodArgsLength(args);
atMethodArgs(args, new int[nargs], new int[nargs],
new String[nargs]);
- bytecode.addInvokespecial(classname, methodname, descriptor);
+ bytecode.addInvokespecial(methodIndex, descriptor);
setReturnType(descriptor, false, false);
addNullIfVoid();
}
jc.recordStaticProceed(classname, methodname);
else if (c == INVOKESPECIAL)
jc.recordSpecialProceed(Javac.param0Name, classname,
- methodname, signature);
+ methodname, signature, index);
else
jc.recordProceed(Javac.param0Name, methodname);
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.InnerClassesAttribute;
+import javassist.expr.ExprEditor;
+import javassist.expr.MethodCall;
public class JvstTest5 extends JvstTestRoot {
public JvstTest5(String name) {
java.lang.annotation.Annotation[] annotations = o.getClass().getDeclaredAnnotations();
assertEquals(1, annotations.length);
}
+
+ public void testProceedToDefaultMethod() throws Exception {
+ CtClass cc = ClassPool.getDefault().get("test5.ProceedDefault");
+ CtMethod mth = cc.getDeclaredMethod("bar");
+ mth.instrument(new ExprEditor() {
+ public void edit(MethodCall c) throws CannotCompileException {
+ c.replace("$_ = $proceed($$) + 10000;");
+ }
+ });
+ cc.writeFile();
+ Object obj = make(cc.getName());
+ assertEquals(21713, invoke(obj, "run"));
+ }
}
--- /dev/null
+package test5;
+
+interface ProceedDefaultI {
+ default int foo() { return 13; }
+}
+
+public class ProceedDefault implements ProceedDefaultI {
+ public int run() { return bar(); }
+ public int foo() { return 1700; }
+ public int bar() {
+ return foo() + ProceedDefaultI.super.foo();
+ }
+}