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

AsmSupport研究心得(二)

闻人宜
2023-12-01

生成类

生成一个无任何成员方法,变量,无继承,无实现的类。

       /**

        * 生成一个无任何成员方法,变量,无继承,无实现的类。

        */

       @Test

       public void testCreateBlankClass(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateBlankClass", null, null);

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

              creator.startup();

       }

 

生成一个有成员变量的类

       /**

        * 生成一个成员变量的类。

        */

       @Test

       public void testCreateMemberVarClass(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateMemberVarClass", null, null);

              creator.createGlobalVariable("globalVar1", Opcodes.ACC_PUBLIC, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar2", Opcodes.ACC_PRIVATE, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar3", Opcodes.ACC_PROTECTED, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar4", Opcodes.ACC_STATIC, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar5", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, AClass.INT_ACLASS);

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

              creator.startup();

       }

变量的可见性可以进行叠加,例如globalVar5,公开的静态成员

 

生成一个有成员变量的类,同时对变量进行初始化

       /**

        * 生成一个成员变量的类。同时对成员变量和静态成员变量进行初始化

        */

       @Test

       public void testCreateMemberVarInitClass(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateMemberVarInitClass", null, null);

              creator.createGlobalVariable("globalVar1", Opcodes.ACC_PUBLIC, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar2", Opcodes.ACC_PRIVATE, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar3", Opcodes.ACC_PROTECTED, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar4", Opcodes.ACC_STATIC, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar5", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, AClass.STRING_ACLASS);

              creator.createConstructor(new AClass[0], new String[0], new InitBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

                            invokeSuperConstructor();

                            assign(getThis().getGlobalVariable("globalVar1"), Value.value("this is globalVar1 init"));

                            assign(getThis().getGlobalVariable("globalVar2"), Value.value("this is globalVar2 init"));

                            assign(getThis().getGlobalVariable("globalVar3"), Value.value("this is globalVar3 init"));

                            runReturn();

                     }

              }, Opcodes.ACC_PUBLIC);

              creator.createStaticBlock(new ClinitBody() {

                     @Override

                     public void body() {

                            assign(getMethodOwner().getGlobalVariable("globalVar4"), Value.value("this is globalVar4 init"));

                            assign(getMethodOwner().getGlobalVariable("globalVar5"), Value.value("this is globalVar5 init"));

                            runReturn();

                     }

              });

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

              creator.startup();

       }

 

assign()方法可用于静态成员、实例成员进行绑定。

静态代码块和接口中用的静态代码块一致。

createConstructor创建构造函数,第一个参数描述输入参数类型,第二个参数描述输入参数名称,第三个参数为InitBody对象。

InitBody对象类似于CinitBody,都拥有形式一样的body(LocalVariable... argus)方法,方法体结束也需要调用runReturn。

在类中或者方法中获取类实例可以使用getThis()方法获取this对象。由于我们创建的globalVariable是非static的。所以通过getThis()获取globalVariable。getThis()对应于java代码中就是this关键字。

 

createConstructor方法有四个参数依次是:

1.         构造方法的所有参数类型的数组

2.         构造方法所有参数的名称

3.         构造参数的方法体

4.         构造方法的修饰符

这个方法中的内容就是我们创建的构造方法里面需要执行的内容了,他有一个变元参数 argus。这里的参数表示的是我们当前创建的构造方法的参数。这个数组中每个LocalVariable和createConstructor方法的第一个参数中的AClass数组一一对应的。

 

要显示的调用invokeSuperConstructor,他的作用就是等同于我们编写java代码的时候调用super()一样。只不过我们在用java创建个构造函数的时候有时候不需要调用super,是应为父类的存在没有参数的构造方法。但这并不代码jvm没有去调用super().其实编译器在编译java的时候已经将调用super的指令加上到了构造方法的字节码中去了。这个方法存在一个变元参数arguments。他表示我们调用super()的时候需要传递的参数,由于我们创建的class没有继承任何类即只继承了Object类,那么我们就不需要传递参数直接调用invokeSuperConstructor();

生成一个有成员变量的类,同时使用构造器对变量初始化

       /**

        * 生成一个有成员变量的类,同时使用构造器对变量初始化

        */

       @Test

       public void testCreateMemberVarInit2Class(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateMemberVarInit2Class", null, null);

              creator.createGlobalVariable("globalVar1", Opcodes.ACC_PRIVATE, AClass.STRING_ACLASS);

              creator.createGlobalVariable("globalVar2", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, AClass.STRING_ACLASS);

              creator.createConstructor(new AClass[]{AClass.STRING_ACLASS, AClass.STRING_ACLASS}, new String[]{"init1", "init2"}, new InitBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

                            invokeSuperConstructor();

                            assign(getThis().getGlobalVariable("globalVar1"), argus[0]);

                            assign(getMethodOwner().getGlobalVariable("globalVar2"), argus[1]);

                            runReturn();

                     }

              }, Opcodes.ACC_PUBLIC);

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

              creator.startup();

       }

 

生成一个类,创建一个成员方法

       /**

        * 生成一个类,创建一个成员方法

        */

       @Test

       public void testCreateMemberMethod1Class(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateMemberMethod1Class", null, null);

              creator.createMethod("method0", new AClass[]{}, new String[]{}, AClass.VOID_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

                           

                     }

              });

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

              creator.startup();

       }

 

成员方法与构造方法类似,唯一不同是最后一个方法体。CommonMethodBody是成员方法的实现逻辑抽象。Argus中的顺序与第2、3参数的顺序一致。

 

 

 

生成一个类,创建一个成员方法,有字符串类型输入,有字符串类型返回,同时将输入的参数输出到标准输出,然后返回该参数

       /**

        * 生成一个类,创建一个成员方法,有字符串类型输入,有字符串类型返回,同时将输入的参数输出到标准输出,然后返回该参数

        */

       @Test

       public void testCreateMemberMethod2Class(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateMemberMethod2Class", null, null);

              creator.createMethod("method0", new AClass[]{AClass.STRING_ACLASS}, new String[]{"input_param"}, AClass.STRING_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

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

                            invoke(systemOut, "println", argus[0]);

                            runReturn(argus[0]);

                     }

              });

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

              creator.startup();

       }

      

使用非生成的的类成员变量,可使用如下方式实现。

1.获取已有类的AClass封装,使用AClassFactory.getProductClass(Class)获取

2.调用AClass对象的获取全局变量方法,getGlobalVariable(String),获取对应名称的静态成员变量。

 

执行一个变量的一个成员方法,可使用如下方式实现

1.获取变量对应的Parameterized封装

2.调用invoke方法,第一个参数为包括该方法的对象Parameterized封装,第二个参数为执行的方法名,第三个参数为参数对应的输入,是一个Parameterized数组。对于重载函数,会根据这个参数自动匹配。

生成一个内部类

目前框架不支持

生成一个内部接口

目前框架不支持

生成一个内部枚举

目前框架不支持

 

生成一个类,实现一个接口

       /**

        * 生成一个类,实现一个接口

        */

       @Test

       public void testCreateImplementInterface(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateImplementInterface", null, new Class[]{FileFilter.class});

              creator.createMethod("accept", new AClass[]{AClassFactory.getProductClass(File.class)}, new String[]{"file"}, AClass.BOOLEAN_ACLASS, null, Opcodes.ACC_PUBLIC, new CommonMethodBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

                            GlobalVariable sysout = AClassFactory.getProductClass(System.class).getGlobalVariable("out");

                            invoke(sysout, "println", argus[0]);

                            runReturn(Value.value(false));

                     }

              });

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

              creator.startup();

       }

 

生成一个类,继承一个类,父类有一个无参构造

       /**

        * 生成一个类,继承一个接口,父类有一个无参构造函数

        */

       @Test

       public void testCreateExtendsParentClassNone(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateExtendsParentClassNone", ParentClass.class, null);

              creator.createConstructor(new AClass[]{}, new String[]{}, new InitBody() {

                     @Override

                     public void body(LocalVariable... argus) {

                            invokeSuperConstructor();

                            GlobalVariable sysout = AClassFactory.getProductClass(System.class).getGlobalVariable("out");

                            invoke(sysout, "println", Value.value("这是一个无参构造"));

                            runReturn();

                     }

              }, Opcodes.ACC_PUBLIC);

              creator.createMethod("method1", new AClass[]{AClass.INT_ACLASS}, new String[]{"i"}, AClass.STRING_ACLASS, new AClass[]{AClassFactory.getProductClass(IOException.class)}, Opcodes.ACC_PUBLIC, new CommonMethodBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

                            GlobalVariable sysout = AClassFactory.getProductClass(System.class).getGlobalVariable("out");

                            invoke(sysout, "println", argus[0]);

                            runReturn(Value.value("this is a extend demo"));

                     }

              });

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

              creator.startup();

       }

 

 

 

生成一个类,继承一个类,父类有一个有参构造

       /**

        * 生成一个类,继承一个接口,父类有一个无参构造函数

        */

       @Test

       public void testCreateExtendsParentClassExist(){

              ClassCreator creator = new ClassCreator(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "generated.create.CreateExtendsParentClassExist", ParentClassA.class, null);

              creator.createConstructor(new AClass[]{AClass.STRING_ACLASS}, new String[]{"msg"}, new InitBody() {

                     @Override

                     public void body(LocalVariable... argus) {

                            invokeSuperConstructor(argus);

                            GlobalVariable sysout = AClassFactory.getProductClass(System.class).getGlobalVariable("out");

                            invoke(sysout, "println", Value.value("这是一个有参构造"));

                            invoke(sysout, "println", argus[0]);

                            runReturn();

                     }

              }, Opcodes.ACC_PUBLIC);

              creator.createMethod("method1", new AClass[]{AClass.INT_ACLASS}, new String[]{"i"}, AClass.STRING_ACLASS, new AClass[]{AClassFactory.getProductClass(IOException.class)}, Opcodes.ACC_PUBLIC, new CommonMethodBody() {

                    

                     @Override

                     public void body(LocalVariable... argus) {

                            GlobalVariable sysout = AClassFactory.getProductClass(System.class).getGlobalVariable("out");

                            invoke(sysout, "println", argus[0]);

                            runReturn(Value.value("this is a extend demo"));

                     }

              });

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

              creator.startup();

       }

 

 

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

 类似资料: