Java: запись истории выполнения в XML - PullRequest
0 голосов
/ 22 сентября 2009

В целях отладки мне нужно следить за выполнением некоторого фрагмента кода внутри класса. Я хотел бы создать журнал для всех вызовов методов в 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 и имеет lot методов, я подумал, есть ли способ общего доступа к параметрам, возможно, с помощью отражения. Я нахожусь внутри метода, и я хочу зациклить на параметрах, заданных для этого вызова метода. Это ослабило бы мою боль и позволило бы мне сделать регулярное выражение для добавления строк журнала. Возможно ли это?

Любой другой изящный способ сделать это приветствуется (но AOP, увы, на самом деле не вариант).

Ответы [ 3 ]

2 голосов
/ 22 сентября 2009

Другой способ - использовать динамический трассировщик, такой как BTrace (похож на AOP, но вне вашего кода). Посмотрите на http://kenai.com/projects/btrace/pages/UserGuide для примеров. Есть даже плагины 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 к вашей работающей программе очень просто. Сначала получите PID вашего процесса, используя jps, после этого вызова:

btrace PID YourCalls.java
2 голосов
/ 22 сентября 2009

Добавить вызов к log() в начале каждого метода. В log() либо создайте исключение (для Java 1.4), либо используйте Thread.currentThread().getStackTrace() для получения трассировки стека.

Это даст вам массив StackTraceElement. Элемент, который вы ищете, находится по индексу 1 (здесь был вызван log()). Используйте getMethodName(), чтобы получить имя метода. После этого вы можете использовать рефлексию для изучения метода.

К сожалению, это не дает вам доступа к реальному стеку Java, поэтому вы не можете распечатать значения параметров. Одним из решений было бы просто скопировать их в вызов журнала и использовать отражение в методе, чтобы выяснить, что они из себя представляют. В Java 5 списки аргументов переменных (log(Object...args)) - ваш друг.

Другой вариант - использовать API Java Debugger и написать небольшой отладчик. В этом случае RemoteStackFrame будет содержать параметры и значения.

Если это слишком много, просто используйте десять строк АОП и покончите с этим.

1 голос
/ 22 сентября 2009

странное предложение:

  1. Открытое затмение
  2. создать подкласс вашего класса с первым классом в конструкторе
  3. изменить конфигурацию eclipse: в шаблоне, где eclipse создает метод делегата, добавьте beginMyMethod (); и endMyMethod (); окружающий делегат.метод ();
  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();
       }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...