om.runjva.instrumentation.LoggerAgent 示例代理
本节列出一个名为 com.runjva.instrumentation.LoggerAgent 示例代理。它操作 java.lang.instrument.ClassFileTransformer 接口并提供所需的 premain(...) 方法。
位于 transform(...) 方法中的实际字节代码操作通过 JBoss "Javassist" 库来实现。这个库提供一个 Java 片断编译器和高级字节代码操作例程。这个编译器允许我们通过创建 Java 字符串片断并编译然后插入到合适的位置进行操作。
签名抽取和返回值字节抽取方法是相当复杂的,并已经被放置在 com.runjva.instrumentation.JavassistHelper 内。它虽然没有列出但在示例代码 .zip 文件中可用。
参阅 参考资料 示例代码部分并链接到 Javassist 和相关背景文章。
用Java Instrumentation在类加载时添加记录(3)
时间:2011-03-05
这是 com.runjva.instrumentation.LoggerAgent 类:
package com.runjva.instrumentation;
import java.lang.instrument.*;
import java.util.*;
import javassist.*;
public class LoggerAgent implements ClassFileTransformer {
public static void premain(String agentArgument,
Instrumentation instrumentation) {
if (agentArgument != null) {
String[] args = agentArgument.split(",");
Set argSet = new HashSet(Arrays.asList(args));
if (argSet.contains("time")) {
System.out.println("Start at " + new Date());
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Stop at " + new Date());
}
});
}
// ... more agent option handling here
}
instrumentation.addTransformer(new LoggerAgent());
}
premain(...) 作为类转换器用来添加 LoggerAgent。它也将字符串参数看作一个逗号分隔的选项列表。如果给出选项 time,则将在此时或停机时打印出日期。
String def = "private static java.util.logging.Logger _log;";
String ifLog = "if (_log.isLoggable(java.util.logging.Level.INFO))";
String[] ignore = new String[] { "sun/", "java/", "javax/" };
public byte[] transform(ClassLoader loader, String className,
Class clazz, java.security.ProtectionDomain domain,
byte[] bytes) {
for (int i = 0; i < ignore.length; i++) {
if (className.startsWith(ignore[i])) {
return bytes;
}
}
return doClass(className, clazz, bytes);
}
用Java Instrumentation在类加载时添加记录(4)
时间:2011-03-05
transform(...) 方法在示例化为实际对象前由系统类加载器加载的每个类调用。每个类都包含载入这些类所需要的代码,避免了对运行时库类添加记录器。需要查看类名称,并返回未修改的库类(注意:分隔符为斜线而不是点)。
private byte[] doClass(String name, Class clazz, byte[] b) {
ClassPool pool = ClassPool.getDefault();
CtClass cl =
|