网管联盟 | 网管论坛 | 网管u家 | 网管博客 | 网管软件 | 网管求职 | 小游戏 | 网管搜索 | 网管原创 | 网管聚合 | 网管读摘 | 网管焦点 | 世界素材 | 会员投稿 | 会员中心 
中国网管联盟
Windows Linux Cisco 网络技术 数据库 黑客攻防 DotNet Java PHP 认证 新闻资讯 服务器 存储资讯 网络设备 网管学堂 技术专题 焦点 网吧频道
 当前位置: > bitsCN.com > JAVA > 新手入门 > 开发工具 > Java 5 特性 Instrumentation 实践  

Java 5 特性 Instrumentation 实践

2006-09-04  作者:网管整理  来源:bitsCN.com  点评 投稿 收藏

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

网管下载dl.bitscn.com

简介 网管网www_bitscn_com

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

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

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

Greeting 代理

中国网管论坛bbs.bitsCN.com

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

public byte[] transform(
    ClassLoader loader, 
    String className, 
    Class cBR, 
    java.security.ProtectionDomain pD, 
    byte[] classfileBuffer) throws IllegalClassFormatException
             中国网管论坛bbs.bitsCN.com 

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

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


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

网管网www.bitscn.com

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

中国网管联盟bitsCN.com

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

中国网管论坛bbs.bitsCN.com


列表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; 
  }
                
网管网www_bitscn_com

网管朋友网www_bitscn_net

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


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

public static void premain(String options, Instrumentation ins) {
    if (options != null) {
System.out.printf("I've been called with options: \"%s\"\n", options);
    }
    else 
      System.out.println("  I've been called with no options.");
    ins.addTransformer(new Greeting());
              } 网管网www_bitscn_com 

网管u家u.bitscn@com

options 参数是通过命令行传递进来的,类似于调用 main 函数时传递的参数。被传递进来的命令行参数是一个完整的字符串,不同于 main 方法,该字符串的解析完全由代理自己负责。列表 3 展示了如何使用命令行调用代理: 中国网管联盟bitsCN.com


列表 3 通过命令行参数调用代理

    
            java -javaagent:Greeting.jar="Hello, Sample" Sample 网管论坛bbs_bitsCN_com 

网管论坛bbs_bitsCN_com

这条命令表示,用参数”Hello, Sample”调用 Greeting 代理,以检测 Sample 类的运行情况。运行该命令之后的结果如下图:

中国网管论坛bbs.bitsCN.com


图2 运行代理 Greeting 的结果
Greeting
网管u家u.bitscn@com

代理需要被打包到一个符合特定标准的 jar 文件中运行。该 jar 文件的 MANIFEST.MF 文件需要包括一些特殊的项以定义代理类等信息。(请查阅 Java 5 规约,获取详细信息)在列表 4 中,我们指定了 Greeting 代理的代理类是 Greeting.class。

网管u家u.bitscn@com


列表4 Greeting 代理的 MANIFEST.MF 文件

    
Manifest-Version: 1.0
Premain-Class: Greeting
             网管u家u.bitsCN.com 

网管bitscn_com

资源 Greeting.jar 文件将包含 Greeting 代理的源代码和类文件,以及使用说明。

网管下载dl.bitscn.com

TAGs   实践   特性   代理   "   ilist.append   运行   import   方法      
 上一篇:新手入门:使用 AppFuse 的七个理由   下一篇:JBuilder 2005开发Applet游戏全接触
Java 5 特性 Instrumentation 实践 评论:
loading.. 评论加载中…
评论:请自觉遵守互联网相关政策法规,评论不得超过250字。

验证码: 注册用户
本类热门排行:
最新推荐文章:
网管论坛交流: