ASM字节码处理框架是用Java开发的而且使用基于访问者模式生成字节码及驱动类到字节码的转换,通俗的讲,它就是对class文件的CRUD,经过CRUD后的字节码可以转换为类。ASM的解析方式类似于SAX解析XML文件,它综合运用了访问者模式、职责链模式、桥接模式等多种设计模式,相对于其他类似工具如BCEL、SERP、Javassist、CGLIB,它的最大的优势就在于其性能更高,其jar包仅30K。Hibernate和Spring都使用了cglib代理,而cglib本身就是使用的ASM,可见ASM在各种开源框架都有广泛的应用。
ASM是一个强大的框架,利用它我们可以做到:
1、获得class文件的详细信息,包括类名、父类名、接口、成员名、方法名、方法参数名、局部变量名、元数据等
2、对class文件进行动态修改,如增加、删除、修改类方法、在某个方法中添加指令等
下面以一个具体实例来演示ASM的强大功能,实现的功能很简单:有一个已经存在的class文件,需要在运行时生成一个该类的子类,并在该类的某个方法中添加几条指令,具体步骤如下:
第一步:定义class文件访问器
public class AsmClassVisit extends ClassAdapter {
private String className; //用于保存原始类名
public AsmClassVisit(ClassVisitor cv) {
super(cv);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
className = name;
superName = name;
name = name + AOPEngine.CHILD_POSTFIX; //定义子类的名字
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);//先得到原始的方法
MethodVisitor newMethod = null;
if("add".equals(name)) //此处的add即为需要修改的方法
{
newMethod = new AsmMethodVisit(mv); //访问需要修改的方法
return newMethod;
}
if("<init>".equals(name)) //还需要改造子类的构造方法
{
newMethod = new ChangeConstructorMethodAdapter(mv, className);
return newMethod;
}
return mv;
}
}
第二步:定义方法访问器:
public class AsmMethodVisit extends MethodAdapter {
public AsmMethodVisit(MethodVisitor mv, String advisorClassName, List<Advisor> advisors) {
super(mv);
this.advisorClassName = advisorClassName;
this.advisors = advisors;
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
super.visitMethodInsn(opcode, owner, name, desc);
}
@Override
public void visitCode() {
//此方法在访问方法的头部时被访问到,仅被访问一次
//此处可插入新的指令
super.visitCode();
}
@Override
public void visitInsn(int opcode) {
//此方法可以获取方法中每一条指令的操作类型,被访问多次
//如应在方法结尾处添加新指令,则应判断:
if(opcode == Opcodes.RETURN)
{
mv.visitTypeInsn(Opcodes.NEW, "com/xyz/Check");//新建一个Check类
mv.visitInsn(Opcodes.DUP);//NEW指令完后,对象的引用将从栈中弹出,而INVOKESPECIAL需要该引用,用DUP指令增加对象的引用
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "com/xyz/Check", "<init>", "()V");//调用构造方法,初始化Check类
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "com/xyz/Check", "checkSecurity", "()V");//调用类中的方法
}
super.visitInsn(opcode);
}
}
第三步:修改子类的构造方法
public class ChangeConstructorMethodAdapter extends MethodAdapter {
private String superClassName;//用于接收父类名
public ChangeConstructorMethodAdapter(MethodVisitor arg0, String superClassName) {
super(arg0);
this.superClassName = superClassName;
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
//如果当前指令是调用父类的构造方法
if (opcode == Opcodes.INVOKESPECIAL && name.equals("<init>")) {
owner = superClassName;
}
super.visitMethodInsn(opcode, owner, name, desc);//改写父类为superClassName
}
}
第四步:读取并动态生成子类
ClassReader cr = new ClassReader(className);//className为原始类名,形如com.xyz.Abc,但在web容器环境下不可这样写
ClassWriter cw = new ClassWriter(false);
AsmClassVisit mv = new AsmClassVisit(cw);
cr.accept(mv, true);
MyspringClassLoader mcl = new MyspringClassLoader(this.getClass().getClassLoader());//定义自己的classLoader,用于根据byte数组load类
Class newClass = mcl.getClass(cw.toByteArray(), null);//生成子类
看得出来,如果需要熟悉运用ASM,需要具备一定的虚拟机指令集等相关知识,而ASM为我们提供了一些辅助工具,可以帮助我们避开直接写指令,如ASMifierClassVisitor和ASMifierCodeVisitor类,这两个类可以将对某个方法的调用进行转换,可以直接得到方法的虚拟机指令。
以上只是ASM的一个简单应用,它所具备的功能远不止这些,灵活使用它可以帮助我们完成看似难以完成的任务。
分享到:
相关推荐
ASM Java字节码操作框架PPT,结合已有AOP实现方法,对比所有对Java字节码操作方法做比较
主要给大家介绍了关于java字节码框架ASM如何操作字节码的相关资料,文中通过示例代码介绍的很详细,有需要的朋友可以参考借鉴,下面来一起看看吧。
字节码生成库是生成和转换java字节码的高级api。
主要给大家介绍了java中字节码框架ASM的相关资料,文中介绍的非常详细,相信对大家的理解和学习具有一定的参考借鉴价值,有需要的朋友们下面来一起学习学习吧。
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class ...
LargeImageMonitor是一个使用ASM进行字节码插桩的大图监控框架,可以对我们要加载的图片进行监控,如果出现图片超过阈值的情况会进行报警。 功能与特点 1.支持Glide,Fresco,Picasso,Universal Image Loader。 2....
ASM是一个java字节码操纵框架,它能被用来动态...asm字节码增强技术主要是用来反射的时候提升性能的,如果单纯用jdk的反射调用,性能是非常低下的,而使用字节码增强技术后反射调用的时间已经基本可以与直接调用相当了
ASM是一个通用的Java字节码操作和...ASM提供与其他Java字节码框架类似的功能,但专注于 性能。因为它的设计和实现尽可能小而且快,所以它非常适合在动态系统中使用(但当然也可以以静态方式使用,例如在编译器中)。
asm4.0字节码操纵框架 asm4.0字节码操纵框架
asm是assembly的缩写,是汇编的称号,对于java而言,asm就是字节码级别的编程。 而这里说到的asm是指objectweb asm,一种.class的代码生成器的开源项目. ASM是一套java字节码生成架构,它可以动态生成二进制格式的...
ASM是一个通用的Java字节码操作和... ASM提供与其他Java字节码框架类似的功能,但专注于性能。 因为它的设计和实现尽可能小而且快,所以它非常适合在动态系统中使用(但当然也可以以静态方式使用,例如在编译器中)。
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class ...
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class ...
ASM是一个JAVA字节码分析、创建和修改的开源应用框架。它可以动态生成二进制格式的stub类或其他代理类,或者在类被JAVA虚拟机装入内存之前,动态修改类。在ASM中提供了诸多的API用于对类的内容进行字节码操作的方法...
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class ...
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class ...
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class ...
ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件...
java使用asm4操作字节码技术,详细介绍了asm如何对java的字节码进行操作,强烈推荐
ASM 是一个 Java 字节码操控框架。它能被用来动态生成类或者增强既有类的功能。这是它的中文指南