【问题标题】:How can I determine which class's `main` method was invoked at runtime?如何确定在运行时调用了哪个类的“main”方法?
【发布时间】:2011-01-14 02:02:20
【问题描述】:

我想动态确定调用了哪个类的 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;
  }
}

感谢您的建议!

【问题讨论】:

  • 我刚刚在我的博客中发表了我对这个话题的想法:alexradzin.blogspot.com/2011/01/get-program-entry-point.html
  • 这是我倾向于的解决方案(验证线程是否命名为 main,在名为 main 的 ThreadGroup 中),但出于我的目的,不需要尽可能通用。如果我需要在更多情况下工作的更通用的解决方案,我肯定会使用这种方法。

标签: java main-method


【解决方案1】:

如果您只需要执行一次即可遍历异常堆栈并查看最后一个类/方法调用。

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

但容易出错。如果我通过反射加载你的类,你会在顶部看到一个完全不同的方法。

您可以尝试 M. Jessup 变体(匹配主方法签名),但如果我也从代码中调用主方法,它将失败。

【讨论】:

    【解决方案2】:

    这有点老套,但您可以使用静态方法 Thread.getAllStackTraces()。这将为您提供 VM 中每个活动线程的堆栈跟踪,并假设启动应用程序的线程仍然活动,您可以检查跟踪并查找其方法签名与 main(String[] args) 匹配的底部元素。

    【讨论】:

    • 嗯。我只需要这样做一次,所以这是一个有趣的选择。
    【解决方案3】:

    Veera Sundar 写了两篇关于如何使用Log4j 的映射诊断上下文(Servlet 过滤器的源代码)http://veerasundar.com/blog/2009/11/log4j-mdc-mapped-diagnostic-context-example-code/ 的文章,可能会针对您的用例进行修改。

    让您的应用程序类(使用 main 方法)将其类名添加为可写入日志文件的变量。

    它比在运行时添加属性工作量少吗?不,不是,而是更优雅

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      • 1970-01-01
      相关资源
      最近更新 更多