我要确定类的名称,其中我的应用程序启动时,一个与main()方法,在运行时,但我在另一个线程和我的堆栈跟踪不走一路回到原来的班级。

我搜索系统属性和类加载器所提供的,并拿出什么一切。是不提供这些信息?

感谢。

有帮助吗?

解决方案 5

我计算出来。谁能告诉我,如果这个环境变量总是会在不同的操作系统其他Java实现在吗?这在Oracle JVM产生像 “org.x.y.ClassName”

的String
public static String getMainClassName() {
  for (final Map.Entry<String, String> entry : System.getenv().entrySet())
    if (entry.getKey().startsWith("JAVA_MAIN_CLASS")) // like JAVA_MAIN_CLASS_13328
      return entry.getValue();
  throw new IllegalStateException("Cannot determine main class.");
}

其他提示

见汤姆Hawtin给出的链接的评论。一种解决方案是这些天(甲骨文JVM仅):

public static String getMainClassAndArgs() {
    return System.getProperty("sun.java.command"); // like "org.x.y.Main arg1 arg2"
}

仅使用Oracle的Java测试7.约特殊情况的更多信息: HTTP:// bugs.java.com/view_bug.do?bug_id=4827318

尝试使用螺纹.getAllStackTraces()。它返回一个地图栈跟踪的所有正在运行的线程,而不只是当前之一。

在JAVA_MAIN_CLASS环境值取决于平台并不总是存在。如果你只是想拿到你的启动Java进程的“主”类的名字,你可以这样做:

  public static String getMainClassName()
  {
    StackTraceElement trace[] = Thread.currentThread().getStackTrace();
    if (trace.length > 0) {
      return trace[trace.length - 1].getClassName();
    }
    return "Unknown";
  } 

鉴于澄清,我建议使用“参数设置从上面”成语。你必须先从信息,不断保持它。

我把在RFE 4827318 (六年前!)这样的事情与测试跑步者使用。

如何是这样的:

Map<Thread,StackTraceElement[]> stackTraceMap = Thread.getAllStackTraces();
for (Thread t : stackTraceMap.keySet())
{
    if ("main".equals(t.getName()))
    {
        StackTraceElement[] mainStackTrace = stackTraceMap.get(t);
        for (StackTraceElement element : mainStackTrace)
        {
            System.out.println(element);
        }
    }
}

这会给你像

java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:231)
java.lang.Thread.join(Thread.java:680)
com.mypackage.Runner.main(Runner.java:10)

在主线程可能是不保证的广告虽然被称为"main" - 可能会更好,以检查包含(main一个堆栈跟踪元素

修改如果主线程已退出,这是没有好!

我建议把这个信息进入系统属性。这通常是简单的,当你开始从脚本您的应用程序做的。

如果你不能做到这一点,我建议设置该属性在每个应用程序的main()方法。这里最简单的方法就是让每一个应用程序得到它的“主类”从一个共同的基类,并运行在那里的初始步骤。我经常这样做对命令行处理:

public class Demo extends Main {
    main(String[] args) {
        Main._main(new Demo (), args);
    }

    // This gets called by Main._main()
    public void run (String[] args) {
    }
}

即使与主()方法的线程已经终止,并且您未使用Oracle JVM仍然可以尝试获取从操作系统的信息。下面的代码获得用来启动Linux下的JVM的命令行,但你可以写一个版本的Windows,等等,那么你可以看看参数传递给JVM找到应用程序的入口点。它可能直接在命令行上,或者你可能有Main-Class的外观:在指定的jar的清单类名。我首先应该使用System.getProperty(“sun.java.command”),并在必要时仅朋友回落至这一机制。

public final static long getSelfPid() {
    // Java 9 only
    // return ProcessHandle.current().getPid();
    try {
        return Long.parseLong(new File("/proc/self").getCanonicalFile().getName());
    } catch( Exception e ) {
        return -1;
    }
}

public final static String getJVMCommandLine() {
    try {
        // Java 9 only
        // long pid = ProcessHandle.current().getPid();
        long pid = getSelfPid();
        byte[] encoded = Files.readAllBytes(Paths.get("/proc/"+pid+"/cmdline"));
        // assume ISO_8859_1, but could look in /proc/<pid>/environ for LANG or something I suppose
        String commandLine = new String( encoded, StandardCharsets.ISO_8859_1 ); 
        String modifiedCommandLine = commandLine.replace((char)0, ' ').trim();
        return modifiedCommandLine;
    } catch( Exception e ) {
        return null;
    }
}`

下面是我使用的是什么,因为你无法控制的情况下主:

public static Class<?> getMainClass() {
  // find the class that called us, and use their "target/classes"
  final Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
  for (Entry<Thread, StackTraceElement[]> trace : traces.entrySet()) {
    if ("main".equals(trace.getKey().getName())) {
      // Using a thread named main is best...
      final StackTraceElement[] els = trace.getValue();
      int i = els.length - 1;
      StackTraceElement best = els[--i];
      String cls = best.getClassName();
      while (i > 0 && isSystemClass(cls)) {
        // if the main class is likely an ide,
        // then we should look higher...
        while (i-- > 0) {
          if ("main".equals(els[i].getMethodName())) {
            best = els[i];
            cls = best.getClassName();
            break;
          }
        }
      }
      if (isSystemClass(cls)) {
        i = els.length - 1;
        best = els[i];
        while (isSystemClass(cls) && i --> 0) {
          best = els[i];
          cls = best.getClassName();
        }
      }
      try {
        Class mainClass = Class.forName(best.getClassName());
        return mainClass;
      } catch (ClassNotFoundException e) {
        throw X_Util.rethrow(e);
      }
    }
  }
  return null;
}

private static boolean isSystemClass(String cls) {
  return cls.startsWith("java.") ||
      cls.startsWith("sun.") ||
      cls.startsWith("org.apache.maven.") ||
      cls.contains(".intellij.") ||
      cls.startsWith("org.junit") ||
      cls.startsWith("junit.") ||
      cls.contains(".eclipse") ||
      cls.contains("netbeans");
}

让主类的另一种方法是寻找在Thread.getAllStackTraces该类,所以你会发现它甚至罐子里面,它适用于任何SDK(开放,甲骨文...):

private static Class<?> mainClass = null;

public static Class<?> getMainClass()
{
    if (mainClass == null)
    {
        Map<Thread, StackTraceElement[]> threadSet = Thread.getAllStackTraces();
        for (Map.Entry<Thread, StackTraceElement[]> entry : threadSet.entrySet())
        {
            for (StackTraceElement stack : entry.getValue())
            {
                try
                {
                    String stackClass = stack.getClassName();
                    if (stackClass != null && stackClass.indexOf("$") > 0)
                    {
                        stackClass = stackClass.substring(0, stackClass.lastIndexOf("$"));
                    }
                    Class<?> instance = Class.forName(stackClass);
                    Method method = instance.getDeclaredMethod("main", new Class[]
                    {
                        String[].class
                    });
                    if (Modifier.isStatic(method.getModifiers()))
                    {
                        mainClass = instance;
                        break;
                    }
                }
                catch (Exception ex)
                {
                }
            }
        }
        return mainClass;
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top