2011-01-13 28 views
1

我想動態地確定哪個類的主要方法被調用,以便更容易地消化組合的日誌文件。如何確定在運行時調用哪個類的main方法?

目前,單個(旋轉的)日誌文件聚集了來自大量守護程序的所有日誌輸出,但是沒有明確的方式來確定日誌條目來自哪個守護程序,因爲所有守護程序都使用共享的代碼庫,並且記錄器是使用log4j的getLogger(Something.class)創建的

由於我們使用自定義Layout類開始,實際輸出信息不是問題,而是發現它。

可以用作回退的一種方法是在調用時定義一個屬性並讀取該屬性。

java -cp ... -Dmain.program=<WHATEVER> MainProgram 

但是,如果能力已經存在,則不需要創建新約定。

更新:對於我而言,以下似乎很好地工作:

import org.apache.log4j.PatternLayout; 
import org.apache.log4j.spi.LoggingEvent; 
public class MyLayout extends PatternLayout { 
    private static String _mainClass = null; 
    public String format(LoggingEvent event) { 
    String mesg = super.format(event); 
    if (mesg.indexOf("$main") > -1) { 
     mesg = mesg.replaceAll("\\$main", getMainClass()); 
    } 
    return mesg; 
    } 
    private static String getMainClass() { 
    if (_mainClass == null) { 
     StackTraceElement[] elem = new Exception().getStackTrace(); 
     int offset = elem.length - 1; 
     if (elem[offset].getMethodName().equals("main")) { 
     _mainClass = elem[offset].getClassName(); 
     } 
     else { 
     _mainClass = "<Unknown_Main_Class>"; 
     } 
    } 
    return _mainClass; 
    } 
} 

感謝您的建議!

+0

我剛剛在我的博客發表了關於此主題的想法:http://alexradzin.blogspot.com/2011/01/get-program-entry-point.html – AlexR 2011-01-13 18:02:20

+0

這是我正在傾向的解決方案(驗證該線程被命名爲main,位於名爲main的ThreadGroup中),但爲了我的目的,不需要儘可能具有通用性。如果我需要一個更通用的解決方案,在更多情況下工作,我肯定會使用這種方法。 – apg 2011-01-14 16:10:09

回答

2

如果你只需要做一次,你可以走異常堆棧並查看最後一個類/方法調用。

StackTraceElement[] elem = new Exception().getStackTrace(); 
    elem[elem.length - 1].getClassName(); 

但容易出錯。如果我通過反射加載你的類,你會在頂部看到一個完全不同的方法。

您可以嘗試M. Jessup變體(匹配主方法簽名),但如果我也從代碼中調用主方法,它將失敗。

1

這有點冒失,但你可以使用靜態方法Thread.getAllStackTraces()。這將爲您獲取VM中每個活動線程的堆棧跟蹤,並假設啓動應用程序的線程仍然存在,您可以檢查這些跟蹤並查找其方法簽名與main(String [] args)匹配的底層元素。

相關問題