Java5特性Instrumentation实践

文章作者 100test 发表时间 2007:03:14 16:50:24
来源 100Test.Com百考试题网


Instrumentation 是 Java 5 提供的新特性。使用 Instrumentation,开发者可以构建一个代理,用来监测运行在 JVM 上的程序。监测一般是通过在执行某个类文件之前,对该类文件的字节码进行适当修改进行的。下文将通过一个具体的例子,来展示 java.lang.instrument 包的工作原理,并且实现了一个测量函数运行时间的代理。

简介

不使用instrumentation 来测量函数运行时间的传统方法是:在函数调用之前记录当前系统时间,在函数调用完成之后再次记录当前系统时间(为了简化描述,本文不考虑虚拟机进程映射到本地操作系统进程时造成的计时误差,详见Use the JVM Profiler Interface for accurate timing)。最后将两次数据的差值作为本次函数运行时间返回。这种方法的弱点在于:

  • 用于性能测量的语句直接夹杂在逻辑代码中
  • 用于性能测量的逻辑是重复的,没有做到代码重用。

使用 instrumentation 提供的功能,结合 Apache 开源项目 BCEL,本文将实现一个用于测量函数运行时间的代理。通过代理技术,用于性能测量的语句与业务逻辑完全分离,同时该代理可以用于测量任意类的任意方法的运行时间,大大提高了代码的重用性。

Greeting 代理

在实现函数运行时间测量代理之前,我们先通过实现一个简单的 Greeting 代理,介绍一下 Java 5 中 instrumentation 的原理。每个代理的实现类必须实现 ClassFileTransformer 接口。这个接口提供了一个

public byte[] transform(

    ClassLoader loader, 

    String className, 

    Class cBR, 

    java.security.ProtectionDomain pD, 

    byte[] classfileBuffer) throws IllegalClassFormatException

            

方法。通过这个方法,代理可以得到虚拟机载入的类的字节码(通过 classfileBuffer 参数)。代理的各种功能一般是通过操作这一串字节码得以实现的。同时还需要提供一个公共的静态方法:
static void premain(String agentArgs, Instrumentation inst)

。一般会在这个方法中创建一个代理对象,通过参数 inst 的 addTransformer() 方法,将创建的代理对象再传递给虚拟机。这个方法是一个入口方法,有点类似于一般类的 main 方法。图1展示了代理工作的原理


图1 代理工作原理
图1 代理工作原理

可以看到,多个代理可以同时执行。这多个代理的 premain 方法将按照代理指定的顺序被依次调用。

下面的代码片断,演示了 Greeting 代理的 transform 方法。在该方法中我们对 agent 的行为进行了简单的定制——输出需要该代理监测的类名。


列表1 输出 Hello, someClass

    

public byte[] transform(ClassLoader loader,

              String className,

              Class cBR, java.security.ProtectionDomain pD,

              byte[] classfileBuffer) 

    throws IllegalClassFormatException

  {

    System.out.println("Hello,\t", className).

    return null. 

  }

               

transform 函数的最后,返回 null 值,表示不需要进行类字节码的转化。定制完代理的行为之后,创建一个 greeting 代理的实例,将该实例传递给虚拟机。


列表2 将 Greeting 代理的实例传递给虚拟机

public static void premain(String options, Instrumentation ins) {

    if (options != null) {

System.out.printf("Ive been called with options: \"%s\"\n", options).

    }

    else 

      System.out.println("  Ive been called with no options.").

    ins.addTransformer(new Greeting()).

              }


相关文章


JBuilder2005开发Applet游戏全接触
Java5特性Instrumentation实践
开发技术:KETTLEJAVAAPI开发实战记录
理解类加载器:J2EE环境下的log4j
澳大利亚华人论坛
考好网
日本华人论坛
华人移民留学论坛
英国华人论坛