快速业务通道

用Java Instrumentation在类加载时添加记录 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-18

用Java Instrumentation在类加载时添加记录

时间:2011-03-05

在分析程序出错的原因时,了解它当时的状态将是非常有用的。在许多情况下,我们可以通过堆栈追踪实现此目的,但这些信息经常都是不可用的,或者您需要的可能是程序在出错时处理数据的相关信息。

传统做法是使用 log4j 和 Java Logging API 等记录框架,然后再通过人工来编写和维护所需的记录语句。这种操作非常单调乏味且容易出错,一般适合自动实现。Java 5 添加的 Java Instrumentation 机制允许您通过提供 "Java 代理" 来检查和修改加载的类字节代码。

本文将展示如何实现这种 Java 代理,它借助标准 Java Logging API 透明地对类中所有方法添加入口和出口记录。以 Hello World 为例:

public class HelloWorld {             public static void main(String args[]) {                        System.out.println("Hello World");            } }

下面是添加了入口和出口记录语句的同一个用例:

import java.util.Arrays; import java.util.logging.Level; import java.util.logging.Logger; public class LoggingHelloWorld {         final static Logger _log = Logger.getLogger(LoggingHelloWorld.class.getName());          public static void main(String args[]) {         if (_log.isLoggable(Level.INFO)) {         _log.info("> main(args=" + Arrays.asList(args) + ")");         }         System.out.println("Hello World");         if (_log.isLoggable(Level.INFO)) {          _log.info("< main()");           }      } }

用Java Instrumentation在类加载时添加记录(2)

时间:2011-03-05

默认记录程序生成的输出格式大体为:

2007-12-22 22:08:52 LoggingHelloWorld main INFO: > main(args=[]) Hello World 2007-12-22 22:08:52 LoggingHelloWorld main INFO: < main()

可以看到,每个记录语句显示为两行:一行显示时间戳、提供的记录名称和生成调用的方法,另一行是提供的记录正文。

本文的其余部分将演示如何通过操作加载的字节代码使原始的 Hello World 程序和有记录的 Hello World 程序有一致的行为效果。使用的操作机制是在 Java 5 中添加 Java Instrumentation。

使用 Java Instrumentation API

您可以通过 JVM arguments 调用 Java -javaagent:youragent.jar 或者 -javaagent:youragent.jar=argument 在试着运行指定的 main 之前使 Java 调用位于 youragent.jar 清单上的 premain(...) 方法。此 premain(...) 方法允许您通过系统类加载器注册类文件 transformer,它能提供 transform(...) 方法。在此后的进程中,此方法会作为每个类的一部分进行调用,而且可以在由类加载器处理为实际 Class 之前操作实际代码。

为此,必须保证实现以下几点:

一个用来实现 ClassFileTransformer 的类。

transform(...) 方法将在每个类载入时被调用。参数是整个类完全的、原始的字节代码。

一个用来提供一个静态空白点 premain() 方法的类。

premain(...) 方法必须通过类加载器注册上面的转换器。它也能处理命令行上的参数。

一个正确的 MANIFEST.MF 文件 .

MANIFEST.MF 必须包含 Pre-Class: .. 行通过 premain() 方法访问类。此外,使用 Boot-Class-Path: 访问外部 .jar 文件.

此代码必须和清单一起放入 .jar 文件,否则它将失败。

c

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号