【发布时间】:2010-05-20 08:10:58
【问题描述】:
我可以检测我的应用程序的主类吗?一个,要么在命令行上给出,要么从命令行给出的 jar 中加载?
如果这不可能,为什么不呢?
编辑:也许我不清楚。我知道我的应用程序总是可以有很多入口点,但是当应用程序运行时,只有一个入口点用于启动当前的 JVM。这是我需要知道的。
【问题讨论】:
标签: java
我可以检测我的应用程序的主类吗?一个,要么在命令行上给出,要么从命令行给出的 jar 中加载?
如果这不可能,为什么不呢?
编辑:也许我不清楚。我知道我的应用程序总是可以有很多入口点,但是当应用程序运行时,只有一个入口点用于启动当前的 JVM。这是我需要知道的。
【问题讨论】:
标签: java
首先,一个应用程序可以有几个入口点。它只是一个包含名为 main 且参数类型为 String[] 的公共静态方法的类。
所以,简短的回答,否,一组类可能有几个可能的入口点。
如果你想列出一个应用程序的所有入口点,你只需要遍历类并寻找这样的 main 方法。
如果你创建一个"runnable jar-file",Manifest 文件中会有一个类似的条目
Main-Class: MyPackage.MyClass
它指定了应用程序的主类。
【讨论】:
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(); } } 没有办法知道调用了两个主方法中的哪一个来启动这个程序(除非你修改主方法来记住哪个之一)。
一种可能性是使用线程的堆栈跟踪并查找启动类。但是,这只有在跟踪位于初始主线程上时才有效。
Throwable t = new Throwable();
StackTraceElement[] elems = t.getStackTrace();
String initClass = elems[elems.length - 1].getClassName();
String initMethod = elems[elems.length - 1].getMethodName();
这也将帮助您了解这有多么困难。最初的主线程甚至不必再运行了。您甚至可以尝试将此检查直接放在其中一个类的 main 静态方法中,但仍然无法正常工作。可以通过反射从另一个类执行 main 方法,并且启动方法本身可能已经在启动线程以外的线程上运行。
对于 Swing 应用程序,标准习惯用法是让启动的主线程在激活第一个表单后终止。因此,在这些情况下,您可以确定主类和启动线程不再运行。
【讨论】:
您可以获得堆栈跟踪,例如
StackTraceElement[] stack = new Throwable().getStackTrace();
在命令行应用程序中,最后一个元素将是主类:
System.out.println(stack[stack.length - 1].getClassName());
servlet、applet 或其他插件更复杂(您必须遍历堆栈,寻找与当前线程具有相同ClassLoader 的类。)
【讨论】:
这很干净:从命令行传入类名作为程序参数。从那里,您可以使用反射等实例化它。
java foo.bar.MyMainClass foo.bar.MyMainClass
【讨论】: