2011-01-13 52 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)匹配的底层元素。

相关问题