【ASM的学习】asm官方手册学习心得02--动态添加或者删除类成员
2013-08-07 14:59
459 查看
【前言】
还记得前面的那几个仿照官方编写的例子吗?今天的例子也是需要用到它。
首先,我们编写一个试验用的类,这个类就用来删除成员函数,添加成员函数等等。
【删除成员函数】
删除成员函数,只需要在classreader进行遍历的时候,classvistor碰到某个函数名称便返回null,即可,具体实验代码:
【removeFunc--classvisitor的子类,重写了遍历方法时候的过滤操作】
【debugVisitor,用于打印字节码】
【主要操作函数】
【相关打印结果】
【补充】
请注意,classwriter这个类也是classvisitor的子类,从上一篇文章我们可以调用visitField这种方法已经隐隐体验到了,现在将classwriter对象放到classvisitor的构造方法里竟然不报错,这就证明了我的想法。
【添加一个参数】
编写一个相关的classvisitor,然后再进行操作:
测试方法:
【测试结果】
【添加函数及修改函数】
下面这个内容肯定是重点了,也是我一直追求的,无论是我编写的代码生成器还是各个工具类库都缺不了灵活性,直接动态生成字节码修改运行方法,添加各种拦截器,reset框架,aop等等高难度技术点都可以实现了,下面先来看看如何添加函数:
还记得前面的那几个仿照官方编写的例子吗?今天的例子也是需要用到它。
首先,我们编写一个试验用的类,这个类就用来删除成员函数,添加成员函数等等。
package TestCase; public class MyTestClass { public String name=""; public int age=0; public int getAge(){ return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName(){ return name; } public boolean isMale=false; public boolean isMale() { return isMale; } public void setMale(boolean male) { isMale = male; } public String getInfoMsg(){ return "【名称】"+getName()+" 【年龄】"+getAge()+" 【是否男性】"+isMale(); } }
【删除成员函数】
删除成员函数,只需要在classreader进行遍历的时候,classvistor碰到某个函数名称便返回null,即可,具体实验代码:
【removeFunc--classvisitor的子类,重写了遍历方法时候的过滤操作】
package TestCase; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; public class removeFuncAdapter extends ClassVisitor { /** * 需要过滤的函数的名称 * */ private String _filterFuncName=""; /** * 需要过滤的函数的参数描述信息,譬如:(I)V,(Ljava/lang/String;)I等等。 * */ private String _filterFuncDescription=""; public removeFuncAdapter(String funcName,String funcDescription,ClassVisitor cv){ super(Opcodes.ASM4,cv); _filterFuncName=funcName; _filterFuncDescription=funcDescription; } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { if(name.equals(_filterFuncName)){ if(desc==null&&_filterFuncDescription==null){ return null; } if(_filterFuncDescription!=null&&_filterFuncDescription.equals(desc)){ return null; } } return cv.visitMethod(access, name, desc, signature, exceptions); } }
【debugVisitor,用于打印字节码】
package TestCase; import org.objectweb.asm.*; /** * Created with IntelliJ IDEA. * User: Administrator * Date: 13-8-7 * Time: 下午2:50 * To change this template use File | Settings | File Templates. */ public class debugClassVistor extends ClassVisitor { public debugClassVistor(){ super(Opcodes.ASM4); } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { System.out.println(" "+name+" extends "+superName+"{"); } @Override public void visitSource(String source, String debug) { } @Override public void visitOuterClass(String owner, String name, String desc) { } @Override public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return super.visitAnnotation(desc,visible); } @Override public void visitAttribute(Attribute attr) { } @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { } @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { System.out.println(" "+desc+" " +name); return super.visitField(access,name,desc,signature,value); } @Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { System.out.println(" "+name+""+desc); return super.visitMethod(access,name,desc,signature,exceptions); } @Override public void visitEnd() { System.out.println("}"); } }
【主要操作函数】
package TestCase; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import java.io.File; public class asm_del_memeber { public static void main(String[] args){ try{ /** * 显示原始的字节码 * **/ System.out.println("====================原始字节码============================="); ClassReader cr1=new ClassReader(MyTestClass.class.getName()); cr1.accept(new debugClassVistor(),0); ClassReader cr=new ClassReader(MyTestClass.class.getName()); ClassWriter cw=new ClassWriter(cr,0) ; removeFuncAdapter vistor1=new removeFuncAdapter("getInfoMsg","()Ljava/lang/String;",cw) ; cr.accept(vistor1,0); cw.visitEnd(); /** * 显示修改以后的字节码 * */ System.out.println("====================修改后字节码============================"); ClassReader cr2=new ClassReader(cw.toByteArray()); cr2.accept(new debugClassVistor(),0); } catch (Exception e){ e.printStackTrace(); } } }
【相关打印结果】
====================原始字节码============================= TestCase/MyTestClass extends java/lang/Object{ Ljava/lang/String; name I age Z isMale <init>()V getAge()I setName(Ljava/lang/String;)V setAge(I)V getName()Ljava/lang/String; isMale()Z setMale(Z)V getInfoMsg()Ljava/lang/String; } ====================修改后字节码============================ TestCase/MyTestClass extends java/lang/Object{ Ljava/lang/String; name I age Z isMale <init>()V getAge()I setName(Ljava/lang/String;)V setAge(I)V getName()Ljava/lang/String; isMale()Z setMale(Z)V } Process finished with exit code 0
【补充】
请注意,classwriter这个类也是classvisitor的子类,从上一篇文章我们可以调用visitField这种方法已经隐隐体验到了,现在将classwriter对象放到classvisitor的构造方法里竟然不报错,这就证明了我的想法。
【添加一个参数】
编写一个相关的classvisitor,然后再进行操作:
package TestCase; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.FieldVisitor; import org.objectweb.asm.Opcodes; public class addFieldAdapter extends ClassVisitor { private String _fieldName=""; private String _fieldDesc=""; private ClassVisitor _cv; private int _fAcc=0; public addFieldAdapter(ClassVisitor cv,int fACC,String fieldName,String fieldDesc){ super(Opcodes.ASM4,cv); _fieldDesc=fieldDesc; _fAcc=fACC; _fieldDesc=fieldDesc; _fieldName=fieldName; _cv=cv; } @Override public void visitEnd() { FieldVisitor fieldVisitor=this.cv.visitField(_fAcc,_fieldName,_fieldDesc,null,null); if(fieldVisitor!=null){ fieldVisitor.visitEnd(); } cv.visitEnd(); } }
测试方法:
package TestCase; import org.objectweb.asm.*; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassWriter; import java.io.File; public class asm_addField_member { public static void main(String[] args){ try{ /** * 显示原始的字节码 * **/ System.out.println("====================原始字节码============================="); ClassReader cr1=new ClassReader(MyTestClass.class.getName()); cr1.accept(new debugClassVistor(),0); ClassReader cr=new ClassReader(MyTestClass.class.getName()); ClassWriter cw=new ClassWriter(cr,0) ; addFieldAdapter visitor1=new addFieldAdapter(cw, Opcodes.ACC_PUBLIC,"test_attribute_1","Ljava/lang/String;"); //removeFuncAdapter vistor1=new removeFuncAdapter("getInfoMsg","()Ljava/lang/String;",cw) ; cr.accept(visitor1,0); cw.visitEnd(); /** * 显示修改以后的字节码 * */ System.out.println("====================修改后字节码============================"); ClassReader cr2=new ClassReader(cw.toByteArray()); cr2.accept(new debugClassVistor(),0); } catch (Exception e){ e.printStackTrace(); } } }
【测试结果】
====================原始字节码============================= TestCase/MyTestClass extends java/lang/Object{ Ljava/lang/String; name I age Z isMale <init>()V getAge()I setName(Ljava/lang/String;)V setAge(I)V getName()Ljava/lang/String; isMale()Z setMale(Z)V getInfoMsg()Ljava/lang/String; } ====================修改后字节码============================ TestCase/MyTestClass extends java/lang/Object{ Ljava/lang/String; name I age Z isMale Ljava/lang/String; test_attribute_1 <init>()V getAge()I setName(Ljava/lang/String;)V setAge(I)V getName()Ljava/lang/String; isMale()Z setMale(Z)V getInfoMsg()Ljava/lang/String; } Process finished with exit code 0下篇预览:
【添加函数及修改函数】
下面这个内容肯定是重点了,也是我一直追求的,无论是我编写的代码生成器还是各个工具类库都缺不了灵活性,直接动态生成字节码修改运行方法,添加各种拦截器,reset框架,aop等等高难度技术点都可以实现了,下面先来看看如何添加函数:
相关文章推荐
- 【ASM的学习】asm官方手册学习心得01
- 学习记录-Qt窗口控件的动态添加和删除
- 利用jQuery来动态为属性添加或者删除属性
- 利用jQuery来动态为属性添加或者删除属性
- XAudio2学习之动态添加删除Voice
- 利用jQuery来动态为属性添加或者删除属性
- Python学习记录02 列表添加和删除元素
- Krpano学习:在javascript中动态添加/删除/修改(位置)热点(向后端写入)
- Hadoop学习记录(5)|集群搭建|节点动态添加删除
- C#入门学习-----选项卡(更改显示样式、动态添加/删除、获得名称)
- Android学习一——动态添加组件与删除,可见性设置,imagebutton简单使用
- Vue实现动态添加或者删除对象和对象数组的操作方法
- 可以动态选取多个或者一个项的js方法。(可以动态添加 删除选项 js)
- js 实现动态的添加或者删除子元素实例
- JAVAEE——BOS物流项目02:学习计划、动态添加选项卡、ztree、项目底层代码构建
- 利用jQuery来动态为属性添加或者删除属性的简单方法
- 利用jQuery来动态为属性添加或者删除属性
- COM动态添加删除成员,类似JavaScript中调用的对象
- js学习(一)-动态添加、修改、删除对象的属性和方法
- 学习笔记2-确认删除操作-动态添加元素、事件-用户注册界面