3

Is there any way to find the name of the main class used to launch the current JVM, from arbitrary code running in that JVM?

By arbitrary, I mean that the code is not necessarily running in the main thread, or may be running in the main thread before main has even been called (e.g., code in a user-supplied java.system.classloader, which runs before main since it's used to load main) - so examining the call stack is not possible.

BeeOnRope
  • 60,350
  • 16
  • 207
  • 386
  • On a JVM, the main method of the main class is called first. (see also http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.1) So, what do you mean "may be running in the main thread before main has even been called". I think this phrase mention "static initializer" or "Thread#run()". – cocoatomo Nov 26 '11 at 00:53
  • @cocoatomo: I'm missing something. Does that link show the solution to the original poster's question? If it does, although I reviewed it, I missed it somehow. – Hovercraft Full Of Eels Nov 26 '11 at 00:56
  • @Hovercraft Full Of Eels: Sorry, I mistook pushing a return key before I had completed my comment. I want to understand BeeOnRope's intent, so I am going to make sure of conditions BeeOnRope hope to meet. – cocoatomo Nov 26 '11 at 01:05
  • Well the JLS may say that, but it's not true in practice. The main class has to be loaded by a ClassLoader, and that ClassLoader is itself an object, whose class must be loaded before main. Typical classloader implementations, like URLClassLoader will use plenty of other classes in their implementation, which will also be loaded before main. This is easy to see if you write your own classloader and install it as the system classloader by specifying the java.system.class.loader property. – BeeOnRope Nov 27 '11 at 06:33

1 Answers1

8

This is the closest I can get and you can take it from here.I can not guarantee that it is truly portable and it will not work if any method is invoking main method of another class.Let me know if you find more clean solution

import java.util.Map.Entry;

public class TestMain {

    /**
     * @param args
     * @throws ClassNotFoundException 
     */
    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println(findMainClass());
    }

    public static String findMainClass() throws ClassNotFoundException{
        for (Entry<Thread, StackTraceElement[]> entry : Thread.getAllStackTraces().entrySet()) {
            Thread thread = entry.getKey();
            if (thread.getThreadGroup() != null && thread.getThreadGroup().getName().equals("main")) {
                for (StackTraceElement stackTraceElement : entry.getValue()) {
                    if (stackTraceElement.getMethodName().equals("main")) {

                        try {
                            Class<?> c = Class.forName(stackTraceElement.getClassName());
                            Class[] argTypes = new Class[] { String[].class };
                            //This will throw NoSuchMethodException in case of fake main methods
                            c.getDeclaredMethod("main", argTypes);
                            return stackTraceElement.getClassName();
                        } catch (NoSuchMethodException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return null;
    }
}
laz
  • 28,320
  • 5
  • 53
  • 50
Adisesha
  • 5,200
  • 1
  • 32
  • 43
  • Thanks, I was aware of this method, but unfortunately it doesn't work for me since it also needs to work before the class containing main is loaded (see my comments added to the question on classloaders). – BeeOnRope Nov 27 '11 at 06:36
  • Accepting this anyway because it does the right thing and I can use it if I'm willing to defer the work I need to do based on the main class. – BeeOnRope Mar 03 '12 at 23:33
  • BTW, if you wanted to avoid more false positives, I think you could look at the class that called main and verify that it's a the expected JDK specific class - although that would introduce a dependence on a specific JDK or JDKs. – BeeOnRope Mar 04 '12 at 00:20