Java 编程的动态性,第 5 部分: 动态转换类
2010-03-18 00:00:00 来源:WEB开发网下面是 JavassistRun 命令行和输出的一个例子,其中使用它来调用 清单 1 中的 Run 应用程序。
[dennis]$java -cp .:javassist.jar JavassistRun Run
onWrite called for Run
Usage: Run main-class args...
运行时定时
我们在 第 4 部分中分析过的方法定时修改对于隔离性能问题来说可能一个很有用的工具,但它的确需要一个更灵活的接口。在该文中,我们只是将类和方法名称作为参数传递给程序,程序加载二进制类文件,添加定时代码,然后写回该类。对于本文,我们将把代码转换为使用加载时修改方法,并将它转换为可支持模式匹配,用以指定要定时的类和方法。
在加载类时更改代码以处理这种修改是很容易的。在清单 4 中的 javassist.Translator 代码的基础上,当正在写出的类名称与目标类名称匹配时,我们可以仅从 onWrite() 调用用于添加定时信息的方法。清单 5 展示了这一点(没有包含 addTiming() 的全部细节――请参阅第 4 部分以了解这些细节)。
清单 5. 在加载时添加定时代码
public class TranslateTiming
{
private static void addTiming(CtClass clas, String mname)
throws NotFoundException, CannotCompileException {
...
}
public static void main(String[] args) {
if (args.length >= 3) {
try {
// set up class loader with translator
Translator xlat =
new SimpleTranslator(args[0], args[1]);
ClassPool pool = ClassPool.getDefault(xlat);
Loader loader = new Loader(pool);
// invoke "main" method of target class
String[] pargs = new String[args.length-3];
System.arraycopy(args, 3, pargs, 0, pargs.length);
loader.run(args[2], pargs);
} catch (Throwable ex) {
ex.printStackTrace();
}
} else {
System.out.println("Usage: TranslateTiming" +
" class-name method-mname main-class args...");
}
}
public static class SimpleTranslator implements Translator
{
private String m_className;
private String m_methodName;
public SimpleTranslator(String cname, String mname) {
m_className = cname;
m_methodName = mname;
}
public void start(ClassPool pool) {}
public void onWrite(ClassPool pool, String cname)
throws NotFoundException, CannotCompileException {
if (cname.equals(m_className)) {
CtClass clas = pool.get(cname);
addTiming(clas, m_methodName);
}
}
}
}
更多精彩
赞助商链接