3

Hoe can I detect the main class of my application? The one, which is either given on the command line or loaded from the jar given at the command line?

If this is not possible, why not?

EDIT: Maybe I wasn't clear. I know there always can be many entry points into my app, but while the app is running, there was only one entry point used to start the current JVM. This is the one I need to know of.

Daniel
  • 27,718
  • 20
  • 89
  • 133
  • 1
    Similar to http://stackoverflow.com/questions/2870291/is-there-a-way-to-know-if-a-java-program-was-started-from-the-command-line-or-fro just yesterday – JoseK May 20 '10 at 08:24

4 Answers4

7

First of all, an application can have several entry points. It is simply a class that contains a public static method called main with the argument type String[].

So, short answer, no, there may be several possible entry points of a set of classes.

If you want to list all entry points of an application, you would simply need to iterate over the classes and look for such main method.

If you create a "runnable jar-file" however, there will be an entry in the Manifest file looking like

Main-Class: MyPackage.MyClass

which specifies the main class of the application.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • All true, but I need the way the current instance of the running program was started WHILE the program runs. – Daniel May 21 '10 at 19:32
  • @Daniel: In that case, his short answer applies. – Powerlord May 21 '10 at 19:46
  • @R. Bemrose: I am sorry, I don't get it. His short answer states that there may be several entry points for a set of classes. This is correct. But I am asking not for all possible entry points, but for the one used to start the current application instance. – Daniel May 23 '10 at 23:54
  • 1
    Consider the following two-class program: `class Test1 { public static void main(String[] args) { new Thread(new SomuRunnable()).start(); } } class Test2 { public static void main(String[] args) { new Thread(new SomuRunnable()).start(); } }` There is no way to tell which of the two main-methods that was invoked to start this program (unless you modify the main-methods to remember which one it was). – aioobe May 24 '10 at 05:41
  • Okey, but when I enter "jps" at the command line, it can tell me. – Daniel May 24 '10 at 17:42
  • 1
    Ah, interesting tool. I didn't know about that! It turns out that jps connects to HotSpot VMs (that is, Suns own virtual machines) and does some instrumentation. That is, it's most probably tied to the specific vm, thus there is probably still no platform-independent solution. (I'm not sure how the jps command is implemented though.) – aioobe May 24 '10 at 18:44
  • I just had a look. It connects the the JVMs and extract some property called "command line", where it does some simple string manipulation to find a main class on a best guess basis. However, when the JVM is started without the usual suspects (java.exe, javaw.exe), but by a custom launcher that uses the JNI interface to embed the JVM, like Exe4J, or the Eclipse IDE executable, then nothing is shown here. So: The answer to my question really seems to be, that it is not possible. – Daniel May 24 '10 at 19:06
1

One possibility would be to use the stack trace of a thread and look for the initiating class. However, this can only work if the trace is on the initial main thread.

Throwable t = new Throwable();
StackTraceElement[] elems = t.getStackTrace();
String initClass = elems[elems.length - 1].getClassName();
String initMethod = elems[elems.length - 1].getMethodName();

This will also help you understand how difficult this can be. The initial main thread does not even have to be running any more. You could even attempt to put this check directly in the main static method of one of your classes and still not work right. It is possible to execute a main method from another class through reflection and that initiating method may itself already be running on a thread other than the initiating thread.

For Swing applications, the standard idiom is to let the initiating main thread terminate after activating the first form. So in these cases you can be certain that the main class and initiating thread are no longer running.

Kevin Brock
  • 8,874
  • 1
  • 33
  • 37
0

You can get a stack trace, e.g.

StackTraceElement[] stack = new Throwable().getStackTrace();

In a command-line application, the last element will be the main class:

System.out.println(stack[stack.length - 1].getClassName());

It is more complicated for servlets, applets or other plugins (you have to iterate through the stack, looking for classes with the same ClassLoader as the current thread.)

finnw
  • 47,861
  • 24
  • 143
  • 221
  • I was typing my similar answer when you submitted yours. However, this won't work very well in most cases (see my answer). – Kevin Brock May 20 '10 at 09:05
  • This will not work in any app which uses multiple threads (Like, every GUI app of us, the Tomcat server apps, etc.) – Daniel May 20 '10 at 09:14
  • Typo in first line since it returns an array. And as @Daniel points out, this could resolve a completely different method. – aioobe May 20 '10 at 10:25
  • Fixed the array part. You're right about the multiple threads problem though. – finnw May 20 '10 at 10:47
0

This is pretty clean: Pass in the class name as a program argument from the command line. From there, you can instantiate it using reflection, etc.

java foo.bar.MyMainClass foo.bar.MyMainClass
thebiggestlebowski
  • 2,610
  • 1
  • 33
  • 30