我目前正在尝试跟踪方法调用以进行学习。
我实施的javagent是this article中实现的修改版本。该程序将任何方法调用记录指令添加到字节码中。不幸的是,bootstrap类加载器拒绝从rt.jar加载任何被操纵的内容。我可以理解这对于生产环境来说不是一个好主意,但对于学生来说这真的很棒。
你有任何想法如何实现这一目标吗?
答案 0 :(得分:0)
您唯一的机会是更改 rt.jar 的内容。引导类加载器在许多方面都很特殊,在代理甚至启动之前,许多(但不是全部)类都被加载。
可以使用redefine
方法显式重新定义某些类。但是,这对于所有引导类都不可能。
答案 1 :(得分:0)
我可以成功地操作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;
}
}
修正了JavassistHelper的方法methodReturnsValue
,以正确区分方法和构造函数。
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
我希望它有所帮助。如果没有,请添加您要执行的操作的更多详细信息。