我目前正在尝试跟踪用于学习目的的方法调用。
我实现的 javagent 是本文实现的修改版本。该程序将任何方法调用记录指令添加到字节码中。不幸的是,引导类加载器拒绝从 rt.jar 加载任何被操纵的内容。我可以理解这对于生产环境来说不是一个好主意,但对于一个学生来说,这将是非常了不起的。
你有什么想法如何做到这一点吗?
我目前正在尝试跟踪用于学习目的的方法调用。
我实现的 javagent 是本文实现的修改版本。该程序将任何方法调用记录指令添加到字节码中。不幸的是,引导类加载器拒绝从 rt.jar 加载任何被操纵的内容。我可以理解这对于生产环境来说不是一个好主意,但对于一个学生来说,这将是非常了不起的。
你有什么想法如何做到这一点吗?
您唯一的机会是更改rt.jar的内容。引导类加载器在许多方面都很特殊,许多(但不是全部)类甚至在代理启动之前就已加载。
某些类可以使用该redefine
方法显式地重新定义。然而,这对于所有引导类都是不可能的。
我可以成功地操作 rt.jar 中的类。
例如,我操纵了BigDecimal
类的字节码。您正在训练哪个课程来操作?你在做什么操作?只是像您提到的文章中那样将日志添加到类的每个方法中?
除了遵循文章的说明之外,我还必须做一些其他的事情才能操作 rt.jar 的类。
在LoggerAgent
课程中,我添加了一组我明确想要操作的类。
String[] includeArr = new String[] { "java/math/BigDecimal" };
ArrayList<String> include = new ArrayList(Arrays.asList(includeArr));
在类的transform
方法中,LoggerAgent
我修改了循环以包含我明确想要操作的类。
for (int i = 0; i < ignore.length; i++) {
if (className.startsWith(ignore[i]) && !include.contains(className)) {
return bytes;
}
}
修复了 methodReturnsValue
JavassistHelper 的方法,以正确区分方法和构造函数。
private static boolean methodReturnsValue(CtBehavior method)throws NotFoundException {
if (method instanceof CtMethod){
CtClass returnType = ((CtMethod) method).getReturnType();
String returnTypeName = returnType.getName();
if(returnTypeName.equals("void")){
return false;
}else{
return true;
}
} else{
return false;
}
}
最后,在 HelloWorld 类中,我创建了一个BigDecimal
只是为了检查操作行为。
输出如下所示:
19/06/2015 16:00:26 java.math.BigDecimal signum
INFO: << signum() returns: 1
19/06/2015 16:00:26 java.math.BigDecimal layoutChars
INFO: << layoutChars(1=true) returns: 11.1099999999999994315658113919198513031005859375
19/06/2015 16:00:26 java.math.BigDecimal toString
INFO: << toString() returns: 11.1099999999999994315658113919198513031005859375
19/06/2015 16:00:26 com.runjva.demo.HelloWorld main
INFO: << main(args=[])
BigDecimal=11.1099999999999994315658113919198513031005859375
Stop at Fri Jun 19 16:00:26 PDT 2015
我希望它有所帮助。如果没有,请添加更多关于您正在尝试做的事情的详细信息。