• java代理的深入浅出(三)-JavaAssist,ASM


    简介

    类似字节码操作方法还有ASM。几种动态编程方法相比较,在性能上Javassist高于反射,但低于ASM,因为Javassist增加了一层抽象。在实现成本上Javassist和反射都很低,而ASM由于直接操作字节码,相比Javassist源码级别的api实现成本高很多。几个方法有自己的应用场景,比如Kryo使用的是ASM,追求性能的最大化。而NBeanCopyUtil采用的是Javassist,在对象拷贝的性能上也已经明显高于其他的库,并保持高易用性。实际项目中推荐先用Javassist实现原型,若在性能测试中发现Javassist成为了性能瓶颈,再考虑使用其他字节码操作方法做优化。

    ASM 是一个 Java 字节码操控框架。它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。
    不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。

    JavaAssist和Asm都是一种在运行时,修改字节码的框架,如下图所示

    JavaAssit和Asm的核心类:

    • ClassWriter
    • MethodVisitor

    JavaAssit的核心类:

    • ClassPool
    • CtClass
    • CtMethod

    示例

    ASM:采用适配模式修改类

    public class TestAsm {
    
        public static void main(String[] args) throws IOException {
            ClassReader classReader = new ClassReader("com.longchao.asm.TestClass");
            ClassWriter classWriter = new ClassWriter(classReader, 0);
            ClassVisitor classVisitor = new ProgrammerClassAdapter(classWriter);
            classReader.accept(classVisitor, 0);
             
        }
    }
    
    public class ProgrammerClassAdapter  extends ClassAdapter{
        public ProgrammerClassAdapter(ClassVisitor classVisitor) {
            super(classVisitor);
        }
        public MethodVisitor visitMethod(int access,String name,String desc,String signature,String[] exceptions){
            MethodVisitor methodVisitor = cv.visitMethod(access,name,desc,signature,exceptions);
            if(null != methodVisitor&& "doCoding".equals(name)){
                methodVisitor = new DoCodingMethodAdapter(methodVisitor);
                return methodVisitor;
    
            }
            return methodVisitor;
        }
    }
    
    public class DoCodingMethodAdapter extends MethodAdapter {
    
        public DoCodingMethodAdapter(MethodVisitor arg0){
            super(arg0);
        }
    
        public void visitCode(){
            super.visitCode();
            mv.visitFieldInsn(Opcodes.GETSTATIC,"System","out","Ljava/io/PrintStream");
            mv.visitLdcInsn("doAsmCode............");
            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V");
    
        }	
    
    }
    

    JavaAssit的示例

    public class TestJavaAssist {
        public static void main(String[] args) throws Exception {
            ClassPool pool = ClassPool.getDefault();
            //创建Programmer类
            CtClass cc= pool.makeClass("com.longchao.Programmer");
            //定义code方法
            CtMethod method = CtNewMethod.make("public void code(){}", cc);
            //插入方法代码
            method.insertBefore("System.out.println("I'm a Programmer,Just Coding.....");");
            cc.addMethod(method);
            //保存生成的字节码
            cc.writeFile("d://temp");
        }
    }
  • 相关阅读:
    AjaxHelper使用范例
    IE浏览器的条件编译指令和微软的ajax实现
    基于AjaxHelper0.41的相册范例程序演示及一个关于博客园的功能建议
    AjaxHelper 0.41
    .Net环境下基于Ajax的MVC方案
    Msys/MinGW与Cygwin/gcc[转]
    常见应用程序的架构
    perl正则表达式[转]
    [CruiseControl] 概念
    MinGW
  • 原文地址:https://www.cnblogs.com/zhulongchao/p/5539802.html
Copyright © 2020-2023  润新知