How to determine main class at runtime in threaded java application?

后端 未结 10 881
野的像风
野的像风 2021-01-01 13:37

I want to determine the class name where my application started, the one with the main() method, at runtime, but I\'m in another thread and my stacktrace doesn\'t go all the

相关标签:
10条回答
  • 2021-01-01 14:29

    I suggest to put this information into a system property. This is usually simple to do when you start your application from a script.

    If you can't do that, I suggest to set the property in the main() method of every application. The most simple way here would be to have every app derive it's "main class" from a common base class and run an init step in there. I often do this for command line processing:

    public class Demo extends Main {
        main(String[] args) {
            Main._main(new Demo (), args);
        }
    
        // This gets called by Main._main()
        public void run (String[] args) {
        }
    }
    
    0 讨论(0)
  • 2021-01-01 14:30

    Here's what I'm using, for situations where you don't control the main:

    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");
    }
    
    0 讨论(0)
  • 2021-01-01 14:38

    See the comments on link given by Tom Hawtin. A solution is these days is (Oracle JVM only):

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

    Tested only with Oracle Java 7. More information about special cases: http://bugs.java.com/view_bug.do?bug_id=4827318

    0 讨论(0)
  • 2021-01-01 14:39

    How about something like:

    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);
            }
        }
    }
    

    This will give you something like

    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)
    

    The main thread is probably not guarenteed to be called "main" though - might be better to check for a stack trace element that contains (main

    Edit if the main thread has exited, this is no good!

    0 讨论(0)
提交回复
热议问题