当前位置: 首页 > 工具软件 > ASMSupport > 使用案例 >

AsmSupport研究心得(一)

燕璞
2023-12-01

使用实例

HelloWorld

package com.woate.learn;

import org.objectweb.asm.Opcodes;

 

import cn.wensiqun.asmsupport.block.method.common.StaticMethodBody;

import cn.wensiqun.asmsupport.clazz.AClass;

import cn.wensiqun.asmsupport.clazz.AClassFactory;

import cn.wensiqun.asmsupport.creator.ClassCreator;

import cn.wensiqun.asmsupport.creator.IClassContext;

import cn.wensiqun.asmsupport.definition.value.Value;

import cn.wensiqun.asmsupport.definition.variable.GlobalVariable;

import cn.wensiqun.asmsupport.definition.variable.LocalVariable;

 

public class HelloWorld {

 

       public static void main(String[] args) {

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.helloworld.HelloWorldExample", null, null);

              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 body(LocalVariable... argus) {

                            invoke(systemOut, "println", Value.value("Hello World"));

                            // don't forget return.

                            runReturn();

                     }

              });

              generate(creator);

       }

 

       public static GlobalVariable systemOut = AClassFactory.getProductClass(System.class).getGlobalVariable("out");

 

       public static Class<?> generate(IClassContext creator) {

              // _这是Class的输出路径。主要为了调试作用。我们通过asmsupport生成的class将获输出到这个路径

              // 你可以通过反编译软件看看我们生成的结果

              creator.setClassOutPutPath(".//target//");

 

              // 这个就是个开关。前面我们把该创建的方法变量都放到了传送带上了。调用startup

              // 启动传送带,将上面的东西一个个处理给我返回一个我们需要的成品(就是class了)

              Class<?> cls = creator.startup();

 

              try {

                     cls.getMethod("main", String[].class).invoke(cls, new Object[] { null });

              } catch (Exception e) {

                     e.printStackTrace();

              }

              return cls;

       }

 

}

 

creator.setClassOutPutPath(".//target//");用于设置字节码生成的根目录。会在根目录根据包名创建文件层次路径。

creator.startup();启动生成字节码过程。

 

生成接口

生成一个空接口,通常适用于标记的接口

       /**

        * 创建一个空的接口,没有任何方法,也无任何成员,继承克隆接口

        */

       @Test

       public void testCreateBlankInterface(){

              InterfaceCreator creator = new InterfaceCreator(Opcodes.V1_6, "generated.create.CreateBlankInterface", new Class[]{Cloneable.class});

              creator.setClassOutPutPath(".//target//");

              creator.startup();

       }

接口创建使用InterfaceCreator,它是AbstractClassCreatorContext的子类,与ClassCreator一样是其子类。

jdk version :JDK的版本。可以用过org.objectweb.asm.Opcodes获取,比如:Opcodes.V1_5表示1.5版本的jdk

class modifiers : 表示创建的Class的修饰符。修饰符同样也是通过org.objectweb.asm.Opcodes获取,比如修饰符是"public abstract"则是 Opcodes.ACC_PUBLIC + Opcodes.ACC_ABSTRACT

the class full name : Class的全名。比如:asmsupport.oschina.TestClass super class。 : 当前创建的class的父类,如果为null则是继承自Object.class。参数类型是class

interfaces : 实现了那些接口,可以是null,类型是Class[]

 

生成一个有变量的接口

       /**

        * 创建一个空的接口,没有任何方法,也无任何成员

        */

       @Test

       public void testCreateVarInterface(){

              InterfaceCreator creator = new InterfaceCreator(Opcodes.V1_6, "generated.create.CreateVarInterface", null);

              //创建一个全局变量,实际是常量,未赋值,那么实际就是null

              creator.createGlobalVariable("globalValue1", AClass.STRING_ACLASS);

              //创建一个全局变量,实际是常量

              creator.createGlobalVariable("globalValue2", AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalValue3", AClass.INT_ACLASS);

              //使用静态代码块对全局变量globalValue2赋值

              creator.createStaticBlock(new ClinitBody() {

                     @Override

                     public void body() {

                            //绑定值字符串到globalValue2

                            assign(getMethodOwner().getGlobalVariable("globalValue2"), Value.value("I'm a global variable at Interface"));

                            //绑定值数字到globalValue3

                            assign(getMethodOwner().getGlobalVariable("globalValue3"), Value.value(5));

                            runReturn();

                     }

              });

              creator.setClassOutPutPath(".//target//");

              creator.startup();

       }

接口中创建的变量需要在静态代码块进行绑定值初始化

字面量可以使用Value.value(字面量值)构建出Parameterized实例。

一个块结束是需要调用return语句。如果无返回值,则调用runReturn();如果有返回值,则调用runReturn(Parameterized)返回值。

getMethodOwner().getGlobalVariable(变量名)可获取接口或者类中定义的全局变量。

assign(ExplicitVariable, Parameterized)可以实现对全局变量的绑定赋值。

注意:全局变量和代码块定义顺序无关。也就是creator.createGlobalVariable("globalValue3", AClass.INT_ACLASS);和creator.createStaticBlock(new ClinitBody() {...});方法调用可以交换。

 

 

Value.value(字面量值)目前支持的类型有

1.Integer

2.Short

3.Byte

4.Boolean

5.Long

6.Double

7.Character

8.Float

9.String

10.AClass

11.Class

 

 

生成一个有方法的接口

       /**

        * 创建一个接口,有方法method1,方法返回值String,方法输入字节,整数

        */

       @Test

       public void testCreateMethodInterface(){

              InterfaceCreator creator = new InterfaceCreator(Opcodes.V1_6, "generated.create.CreateMethodInterface", null);

              creator.createMethod("method1", new AClass[]{AClass.BYTE_ACLASS, AClass.INT_ACLASS}, AClass.STRING_ACLASS, new AClass[]{AClassFactory.getProductClass(IOException.class)});

              creator.setClassOutPutPath(".//target//");

              creator.startup();

       }

InterfaceCreator.createMethod()用于创建方法。输入参数为第二个参数AClass数组,按数组顺序描述方法参数输入的顺序。第三个参数AClass,定义了方法的返回类型。第四个参数AClass数组,描述了异常列表。

 

 

生成一个有内部类的接口,目前此框架不支持

 

 

 

生成枚举

生成一个没有任何值的枚举

目前框架不支持

生成一个只有常量值的枚举

       /**

        * 生成一个只有常量值的枚举

        */

       @Test

       public void testCreateConstantEnum(){

              EnumCreator creator = new EnumCreator(Opcodes.V1_6, "generated.create.CreateConstantEnum", null);

              creator.createEnumConstant("Monday");

              creator.setClassOutPutPath(".//target//");

              creator.startup();

       }

 

生成一个只有常量值的枚举,同时使用构造器进行初始化

目前框架不支持

转载于:https://my.oschina.net/woate/blog/379533

 类似资料: