【问题标题】:Java : logging execution history as XMLJava:将执行历史记录为 XML
【发布时间】:2010-11-30 07:54:26
【问题描述】:

出于调试目的,我需要在一个类中跟踪某段代码的执行情况。我想以 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 并且有 lots 方法,我想知道是否有一种方法可以通用地访问参数,也许使用反射。我在方法内部,我想循环给这个方法调用的参数。它会减轻我的痛苦,并允许我制作一个正则表达式来添加日志行。有可能吗?

任何其他巧妙的方法都值得赞赏(但 AOP 并不是一个真正的选择)。

【问题讨论】:

  • 为什么不能选择 AOP?这就像说 OOP 不是一种选择。
  • 如果这是为了调试,为什么不使用调试器呢?
  • 是的斯卡夫曼。调试器+记事本。甚至在整个地方都进行系统输出。当然它不性感,但它很有效。
  • 伙计们,请提供帮助。 AOP 不是一个选项,因为 OOP 也不是,我在这里处理的是全过程 Java。而且我正在努力为自己节省数小时的 F5 击球时间。
  • @subtenante:我们试图提供帮助,但无缘无故排除最佳选择并不能帮助我们帮助您。你真的知道 AOP 涉及什么,或者你只是把它写下来了吗?

标签: java reflection parameters methods


【解决方案1】:

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

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

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

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

如果工作量太大,只需使用十行 AOP 就可以了。

【讨论】:

    【解决方案2】:

    奇怪的建议:

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

    类似:

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

    【讨论】:

      【解决方案3】:

      另一种方法是使用 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-10
        • 1970-01-01
        • 2014-09-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-10
        相关资源
        最近更新 更多