为了调试目的,我需要跟踪类中某些代码的执行情况。我想用XML为所有方法调用生成一个日志,例如:
<call class='pack.age.MyClass' method='myMethod1'>
<param name='param1'>param1.toString() value</param>
...
<call>Call to other method within myMethod1; you get the idea</call>
</call>因为这个类是long,并且有很多方法的,所以我想知道是否有一种一般地访问参数的方法,也许可以使用反射。我在这个方法中,我想循环这个方法调用的参数。这将减轻我的痛苦,并允许我做一个regexp添加日志行。有可能吗?
任何其他简洁的方法都能让人赏识(但是AOP,唉,这并不是一个真正的选择)。
发布于 2009-09-22 08:51:48
另一种方法是使用像BTrace这样的动态跟踪器(类似于AOP,但在代码之外)。看看BTrace's wiki的例子。甚至还有VisualVM插件可以附加到运行过程中,使事情变得更容易。使用下面的BTrace代码,您将得到方法调用及其参数(取自示例)。
import com.sun.btrace.AnyType;
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
@BTrace public class YourCalls {
@OnMethod(clazz="pack.age.MyClass", method="myMethod1",
location=@Location(value=Kind.CALL, clazz="/.*/", method="/.*/"))
public static void o(AnyType[] args) { // all calls to methods
printArray(args);
}
} 将BTrace附加到运行中的程序是很容易的。首先使用jps获取进程的PID,在此调用之后:
btrace PID YourCalls.java发布于 2009-09-22 08:01:18
在每个方法的开头添加对log()的调用。在log()中,要么抛出异常(对于Java1.4),要么使用Thread.currentThread().getStackTrace()获取堆栈跟踪。
这将为您提供一个StackTraceElement数组。您要查找的元素位于索引1(这是调用log()的地方)。使用getMethodName()获取方法的名称。之后,您可以使用反射来检查该方法。
不幸的是,这不能让您访问真正的Java堆栈,因此无法打印参数的值。一种解决方案是简单地将它们复制到日志调用中,并使用方法上的反射来确定它们是什么。在Java5中,变量参数列表(log(Object...args))是您的朋友。
另一个选项是使用Java调试器API并编写一个小型调试器。在本例中,RemoteStackFrame将包含参数和值。
如果这是太多的工作,只需使用十行AOP并完成它。
发布于 2009-09-22 08:12:37
怪异的建议:
类似于:
class A
{
public void sayHello()
{
System.err.println("OK");
}
}
class B
extends A
{
private A delegate;
public B(A delegate) { this.delegate=delegate);}
@Override
public void sayHello()
{
beginMyMethod();
delegate.sayHello();
endMyMethod();
}
}https://stackoverflow.com/questions/1458678
复制相似问题