2009-09-22 96 views
0

爲了調試目的,我需要在類中執行一段代碼。我想生成一個日誌所有方法調用,在XML,如:Java:以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唉,不是一個真正的選擇)。

+0

爲什麼AOP不是一個選項?這就像說OOP不是一種選擇。 – skaffman 2009-09-22 07:49:58

+0

如果這是出於調試目的,爲什麼不使用調試器? – skaffman 2009-09-22 07:53:36

+0

是skaffman。調試器+記事本。甚至在所有地方都有系統。當然這不是性感,但它是有效的。 – 2009-09-22 07:57:21

回答

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", 
       [email protected](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

在每個方法的開始處添加對log()的調用。在log()內部拋出異常(對於Java 1.4)或使用Thread.currentThread().getStackTrace()來獲取堆棧跟蹤。

這會給你一個StackTraceElement的數組。您要查找的元素位於索引1處(這是調用log()的地方)。使用getMethodName()獲取方法的名稱。之後,您可以使用反射來檢查方法。

不幸的是,這並不能讓您訪問真正的Java堆棧,因此您無法打印參數的值。一種解決方案是簡單地將它們複製到日誌調用中,並使用對該方法的反思來弄清楚它們是什麼。使用Java 5,可變參數列表(log(Object...args))是您的朋友。

另一種選擇是使用Java Debugger API並編寫一個小調試器。在這種情況下,RemoteStackFrame將包含參數和值。

如果這是太多的工作,只需使用十行AOP並完成它。

1

怪異建議:

  1. 打開Eclipse
  2. 在構造
  3. modifiy月食的配置創建類的子類與第一類:在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(); 
     } 
    }