选择显示字体大小

代码动态生成利器asm

小巧而神奇的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 br.neton负责。从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});
  }
}



 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons