这一节我们讲如何用ASMSupport生成方法调用的操作,方法调用包括下面四种类型:
首先我们需要看我们想要生成的类:
代码1:
package generated.operators;import java.io.PrintStream;
public class MethodInvokeOperatorGenerateExample
{
public String toString()
{return "description is \"" + super.toString() + "\"";
}
public String description()
{return toString();
}
public static String getDescription(MethodInvokeOperatorGenerateExample obj)
{return obj.description();
}
public static void main(String[] args)
{MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample(); System.out.println("Call static method : " + getDescription(obj));
}
}
这里面包括了所有的方法调用的类型。
调用构造方法我们是用的是public final MethodInvoker invokeConstructor(AClass owner, Parameterized... arguments)方法,同样也是ProgramBlock的方法,
这个方法有两个参数:
在代码1中,我们有MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample();代码是调用构造方法,那我们对应的asmsupport的代码如下:
invokeConstructor(getMethodOwner())
这里有个getMethodOwner()方法,这个方法就是获取当前生成的class或修改的class,由于我们正在创建class MethodInvokeOperatorGenerateExample,所以这里getMethodOwner()获得的AClass就是MethodInvokeOperatorGenerateExample
调用静态方法我们使用的是public final MethodInvoker invokeStatic(AClass owner, String methodName, Parameterized... arguments)方法,
参数:
在代码1中,getDescription方法就是静态方法,而getDescription(obj)正好是调用静态方法。对应的asmsupport的代码如下:
invokeStatic(getMethodOwner(), "getDescription", obj)
这里的obj是上面我们通过构造函数构造的对象,这里作为getDescription的参数。
调用静态方法我们使用的是public final MethodInvoker invoke(Parameterized caller, String methodName, Parameterized… arguments)方法,
参数:
在代码1中的getDescription方法内,我们调用了”obj.description();”语句,那么对应的asmsupport的代码如下:
invoke(argus[0], "description")
这里的argus[0]表示当前方法的第一个参数
调用当前类和调用父类的方法其实和调用非静态方法很相似,唯一的区别就是我们传入的第一个参数。在java代码中使用this和super关键字表示当前的和父类的,那么我们同样在asmsupport中也有相应的方法:
当然,如果当前类中没有重写父类的方法,我们直接调用getThis()方法并将其返回值传入invoke方法作为调用父类方法。这个和java代码中一样的,比如代码1中的代码:
public String description() { return toString(); }
这里面其实就是调用了父类的方法,但是我们这里使用this.toString()或者super.toString()都可以,所以这里我们使用如下asmsupport代码:
/*this.toString()*/ invoke(getThis(), "toString") /*super.toString()*/ invoke(getSuper(), "toString")
package example.operators; import org.objectweb.asm.Opcodes; import jw.asmsupport.block.method.common.CommonMethodBody; import jw.asmsupport.block.method.common.StaticMethodBody; import jw.asmsupport.clazz.AClass; import jw.asmsupport.clazz.AClassFactory; import jw.asmsupport.creator.ClassCreator; import jw.asmsupport.definition.value.Value; import jw.asmsupport.definition.variable.LocalVariable; import jw.asmsupport.operators.method.MethodInvoker; import example.AbstractExample; public class MethodInvokeOperatorGenerate extends AbstractExample { /** * @param args */ public static void main(String[] args) { ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC , "generated.operators.MethodInvokeOperatorGenerateExample", null, null); creator.createMethod("toString", null, null, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody(){ @Override public void generateBody(LocalVariable... argus) { //通常我们将super看作是一个变量所以我们用invoke(Parameterized caller, String methodName, Parameterized... arguments) //方法实现super.xxxx。通过getSuper方法获取super变量 MethodInvoker superToString = invoke(getSuper(), "toString"); runReturn(append(Value.value("description is \""), superToString, Value.value("\""))); } }); /** * 实现如下方法 * public String description(){ * return toString(); * } * */ creator.createMethod("description", null, null, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody(){ @Override public void generateBody(LocalVariable... argus) { /** * 这里和调用super.xxx是一样的。调用当前类中的非静态方法都是通过 * invoke(Parameterized caller, String methodName, Parameterized... arguments)方法调用。 * 通过getThis方法获取this变量 */ runReturn(invoke(getThis(), "toString")); } }); /** * 生成如下方法的字节码: * public static String getDescription(MyObject obj){ * return obj.description(); * } */ creator.createStaticMethod("getDescription", new AClass[]{creator.getCurrentClass()}, new String[]{"obj"}, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, new StaticMethodBody(){ @Override public void generateBody(LocalVariable... argus) { /** * 和上面。 * 这里argus[0]就是我们定义的参数obj。如果需要传递参数可以直接在 * 方法调用的时候添加需要传递的参数,因为这是个变元方法 */ runReturn(invoke(argus[0], "description")); } }); /** * public static void main(String[] args){ * MyObject obj = new MyObject(); * System.out.println("Call static method : " + MyObject.getDescription(obj)); * } */ creator.createStaticMethod("main", new AClass[]{AClassFactory.getProductClass(String[].class)}, new String[]{"args"}, null, null, Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, new StaticMethodBody(){ @Override public void generateBody(LocalVariable... argus) { /** * 首先调用构造方法生成MethodInvokeOperatorGenerateExample obj = new MethodInvokeOperatorGenerateExample(); * 通过invokeConstructor方法实现调用构造方法 * 这个方法后两个参数。 * 1.表示需要构造的类,这里我们通过调用getMethodOwner获取当前操作类 * 2.表示构造方法的参数。这个参数是个变元参数 */ LocalVariable obj = createVariable("obj", getMethodOwner(), false, invokeConstructor(getMethodOwner())); /** * 实现System.out.println("Call static method : " + MyObject.getDescription(obj)); * 这里将学习到如何生成调用静态方法 * * 调用静态方法是通过invokeStatic(AClass owner, String methodName, Parameterized... arguments) * 实现的。 * 这个方法有三个参数 * 1.通过那个Class调用静态方法。 * 2.静态方法的名称 * 3.参数 */ MethodInvoker getDescriptionInvoker = invokeStatic(getMethodOwner(), "getDescription", obj); invoke(systemOut, "println", append(Value.value("Call static method : "), getDescriptionInvoker)); runReturn(); } }); generate(creator); } }
更多教程
更多教程