`

代码动态生成利器ASM

阅读更多

 

前言

     代码生成器(code generator,CG),顾名思义就是生成代码的工具。有了它,你就可以从一组简单的设定或者数据库设计中获得几百、几千行代码。如果不采用这项技术的话,开发者就不得不花上几个小时或者几天的时间来手工编写这些代码。另一方面,优秀的开发工具为了提供其独特的功能或者屏蔽一些容易出错的细节,也往往采用代码生成技术为使用者提供一个程序的模板框架,其目的也是为了提高编程的效率。以上观点仅是对代码生成器的一般理解,换句话说,这似乎是一个可有可无的东西,没有它,不过是多费一些人工而已。然而,本文要介绍的这套名为ASM的JAVA工具类的功能非同小可,它可以生成JAVA字节码,也就是class文件。你可以在应用程序中根据情况动态生成各式各样的class,然后就调用,达到一种近乎上帝造物般的神奇。心动不如行动,如果你也想在自己的开发中引入这一超前的编程技术,请看此文。

 

小巧而神奇的ASM

     ASM是一套JAVA字节码生成架构。它可以动态生成二进制格式的stub类或其他代理类,或者在类被JAVA虚拟机装入内存之前,动态修改类。ASM 提供了与 BCEL( http://jakarta.apache.org/bcel)和SERP( http://serp.sourceforge.net/ )相似的功能,只有22K的大小,比起350K的BCEL和150K的SERP来说,是相当小巧的,并且它有更高的执行效率,是BCEL的7倍,SERP的11倍以上。ASM一贯的设计思想就是将其应用于动态生成领域,因此小巧和快捷一直是这个产品的设计和实现的指导思想。

   

   此产品由法国电信公司的研发工程师Eric Bruneton负责。从2002年7月ASM的第一个版本发布至今,此产品已经升级了五次,日臻完美。到目前为止,ASM最新的版本是1.3.5,你可以去http://asm.objectweb.org/ 下载。

   

   ASM的最终目标是创建一个生成工具,可以被用来执行对任何类的处理操作(不像一些工具,比如Javassit,它只支持预先定义的类操作,然而在许多场合这一功能是有局限性的)。

 

JAVA的CLASS文件格式

     要想驾驭ASM,先要了解一下JAVA的CLASS文件格式。JAVA的CLASS文件通常是树型结构。根节点包含以下元素:

  ConstantPool:符号表;

  FieldInfo:类中的成员变量信息;

  MethodInfo:类中的方法描述;

  Attribute:可选的附加节点。


  FieldInfo节点包含成员变量的名称,诸如public,private,static等的标志。ConstantValue属性用来存储静态的不变的成员变量的值。Deprecated和Synthetic被用来标记一个成员变量是不被推荐的或由编译器生成的。


  MethodInfo节点包含方法的名称,参数的类型和和它的返回值,方法是公有的,私有的或静态的等标志。MethodInfo包含可选的附加属性,其中最重要的是Code属性,它包含非抽象的方法的代码。Exceptions属性包含方法将抛出的Exception的名称。Deprecated和Synthetic属性的信息同上面的FieldInfo的定义一样。


  根节点的可选属性有SourceFile,InnerClasses和Deprecated。SourceFile用来存储被编译成字节码的源代码文件的原始名称;InnerClasses存储内部类的信息。由于这些属性的存在,java 的类格式是可以扩展的,也就是说可以在一个class中附加一些非标准的属性, java虚拟机会忽略这些不可识别的属性,正常的加载这个class。


  ConstantPool是一个由数字或字符串常量的索引组成的队列,或由此类的树的其他节点引用的,由其他对象创建的被引用常量的索引组成的队列。这个表的目标是为了减少冗余。例如,FieldInfo节点不包含节点的名称,只包含它在这一表中的索引。同样的,GETFIELD和PUTFIELD不直接包含成员变量的名称,只包含名称的索引。


精通ASM

     Asm架构整体都围绕着两个接口,即ClassVisitor 和 CodeVisitor,它们能访问每个类的方法,成员变量,包含在每个方法中的字节码指令。ClassReader用来读取class文件;ClassWriter类用来写生成的Class文件。


  为了修改已经存在的class,你必须使用分析class文件的ClassReader,类的修正器和写class文件的ClassWriter。类的修正器就是一个ClassVisitor,它可以委派一部分工作到其他的ClassVisitor,但是为了实现预期的修改步骤,它将改变一些参数的值,或者调用一些其他方法。为了比较容易的实现这种类的修正器,ASM提供了一个ClassAdapter和CodeAdapter,这两个适配器类分别实现了ClassVistor和CodeVistor接口。


HelloWorld,体验造类的神奇

     下面是一个应用ASM动态生成字节码的类,并调用其中方法的完整的HelloWorld 程序,程序的功能是动态生成一个Example.class类,并实例化一个Example对象,调用对象的main函数,在屏幕上打印出"Hello world!"

 

 

  import org.objectweb.asm.*;
  import java.lang.reflect.*;
  import java.io.FileOutputStream;
  public class Helloworld extends ClassLoader implements Constants {
  public static void main (final String args[]) throws Exception {
  /*
  * 此程序将生成一个class,对应的java源代码是:
  *
  * public class Example {
  * public static void main (String[] args) {
  * System.out.println("Hello world!");
  * }
  * }
  *
  */
  // 创建一个ClassWriter
  ClassWriter cw = new ClassWriter(false);
  cw.visit(ACC_PUBLIC, "Example", "java/lang/Object", null, null);
  // 创建一个 MethodWriter
  CodeVisitor mw = cw.visitMethod(ACC_PUBLIC, "", "()V", null);
  // 推入 'this' 变量
  mw.visitVarInsn(ALOAD, 0);
  // 创建父类的构造函数
  mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V");
  mw.visitInsn(RETURN);
  // 这段代码使用最多一个栈元素和一个本地变量
  mw.visitMaxs(1, 1);
  // 为main方法创建一个MethodWriter
  mw = cw.visitMethod(
  ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null);
  // 使用System类的out成员类
  mw.visitFieldInsn(
  GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
  // pushes the "Hello World!" String constant
  mw.visitLdcInsn("Hello world!");
  // 调用System.out的'println' 函数
  mw.visitMethodInsn(
  INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
  mw.visitInsn(RETURN);
  // 这段代码使用最多两个栈元素和两个本地变量
  mw.visitMaxs(2, 2);
  // 生成字节码形式的类
  byte[] code = cw.toByteArray();
  FileOutputStream fos = new FileOutputStream("Example.class");
  //写文件
  fos.write(code);
  //关闭输出流
  fos.close();
  //实例化刚刚生成的类
  Helloworld loader = new Helloworld();
  Class exampleClass = loader.defineClass("Example", code, 0, code.length);
  // 使用动态生成的类打印 'Helloworld'
  Method main = exampleClass.getMethods()[0];
  main.invoke(null, new Object[] {null});
  }
  }

 

 

 参考文章:

http://blog.csdn.net/axman/article/details/4268189

http://blog.csdn.net/axman/article/details/4285759

http://melin.iteye.com/blog/709594

 http://blog.csdn.net/songyongfeng/article/details/6950902

 

 

分享到:
评论

相关推荐

    ASM操作字节码,动态生成Java类class文件

    ASM操作字节码,动态生成Java类class文件,模拟Spring的AOP实现原理。

    代码生成工具asm-3.2

    代码生成工具asm-3.2 下载地址:http://asm.ow2.org/

    asm动态生成class,并且动态加载执行

    NULL 博文链接:https://name327.iteye.com/blog/1554558

    JavaEE源代码 asm-attrs

    JavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-attrsJavaEE源代码 asm-...

    AOP 的利器 ASM 3.0

    介绍ASM的简单使用和基本原理,并对AOP的原理进行了详细的描述和总结。

    JavaEE源代码 asm-2.2.2

    JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2JavaEE源代码 asm-2.2.2...

    学习asm汇编的代码

    学习asm汇编的代码

    ASM4使用指南

    它可以用于修改现有类或直接以二进制形式动态生成类。ASM提供了一些常见的字节码转换和分析算法,可以从中构建自定义复杂转换和代码分析工具。ASM提供与其他Java字节码框架类似的功能,但专注于 性能。因为它的设计...

    AOP 的利器:ASM 3_0 介绍

    AOP 的利器:ASM 3_0 介绍,很好的书

    图形点阵LCD代码生成器

    图形点阵LCD代码生成器。...运行本程序后,通过简单的操作就可将指定图形文件的点阵根据设置的属性(字节方向、字位顺序等)转化为十六进制的数据,生成图形点阵代码文件“IMAGELIB.ASM”或者“imagelib.c”。

    HEX2ASM单片机 hex文件生成asm文件

    可以将keil、wave生成的hex文件反汇编成汇编语言

    wd动态代码ASM1111

    从内存中动态抽取的warden代码! 从内存中动态抽取的warden代码!从内存中动态抽取的warden代码!从内存中动态抽取的warden代码!

    远程线程注入asm代码

    远程线程注入asm代码.hello world级别 xxxxxxxxxxx

    W32asm反汇编利器绿色版.rar

    W32asm反汇编利器绿色版.rar W32asm反汇编利器绿色版.rar W32asm反汇编利器绿色版.rar

    红外遥控解码 ASM 程序 源代码

    红外遥控解码 ASM 程序 源代码,很经典的拿去改改就可以直接使用了

    c32asm 代码编辑程序更改标题图标

    c32asm 代码编辑程序更改标题图标c32asm 代码编辑程序更改标题图标c32asm 代码编辑程序更改标题图标c32asm 代码编辑程序更改标题图标c32asm 代码编辑程序更改标题图标c32asm 代码编辑程序更改标题图标c32asm 代码...

    asm5.0安装包

    ASM是一套java字节码生成架构,它可以动态生成二进制格式的stub类或其它代理类, 或者在类被java虚拟机装入内存之前,动态修改类。 现在挺多流行的框架都使用到了asm.所以从aop追溯来到了这。

    Asm汇编代码转换器

    Asm汇编代码转换器 AsmToE 就是 Asm汇编语言转易语言的置入代码的工具 此工具有双引擎 ------ Masm引擎 跟 OD引擎 Masm引擎兼较好 OD引擎兼容性(我都不想吐槽) 汇编功能支持 代码高亮 (亮瞎我的狗眼啊..魂淡) ...

    单片机课程设计代码(asm)

    用于期末课程设计 我们是用于实习的 单片机实习 代码都已经测试通过 单片机课程设计代码 asm

    asm官方代码文档

    asm官方代码文档

Global site tag (gtag.js) - Google Analytics