Java:将执行历史记录为XML

时间:2009-09-22 07:48:37

标签: java reflection parameters methods

出于调试目的,我需要在类中执行某些代码。我想用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>

因为这个类是并且很多的方法,我想知道是否有办法一般地访问参数,可能使用反射。我在方法内部,我想循环给这个方法调用的参数。它可以减轻我的痛苦,让我做一个正则表达式来添加日志行。有可能吗?

任何其他简洁的方式来表达赞赏(但AOP不是一个真正的选择)。

3 个答案:

答案 0 :(得分:2)

在每个方法的开头添加对log()的调用。在log()内,要么抛出异常(对于Java 1.4),要么使用Thread.currentThread().getStackTrace()来获取堆栈跟踪。

这将为您提供StackTraceElement的数组。您要查找的元素位于索引1(这是调用log()的位置)。使用getMethodName()获取方法的名称。之后,您可以使用反射来检查方法。

不幸的是,这不会让您访问真正的Java堆栈,因此您无法打印参数的值。一种解决方案是简单地将它们复制到日志调用中,并使用方法上的反射来确定它们是什么。使用Java 5,可变参数列表(log(Object...args))是您的朋友。

另一个选项是使用Java Debugger API并编写一个小调试器。在这种情况下,RemoteStackFrame将包含参数和值。

如果这工作太多,只需使用十行AOP即可完成。

答案 1 :(得分:2)

另一种方法是使用像BTrace这样的动态跟踪器(类似于AOP,但在代码之外)。请查看http://kenai.com/projects/btrace/pages/UserGuide示例。甚至还有VisualVM插件可以附加到正在运行的进程,这使得thigs更容易。使用以下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

答案 2 :(得分:1)

奇怪建议:

  1. 打开eclipse
  2. 使用构造函数
  3. 中的第一个类创建类的子类
  4. 修改eclipse的配置:在eclipse创建委托方法的模板中,添加一个beginMyMethod();和一个endMyMethod();围绕delegate.method();
  5. 请求eclipse实现所有委托方法。此解决方案不适用于私有和静态成员。
  6. 类似的东西:

     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();
           }
       }