从Java代码中查找主类名称的可移植方法

从Java代码中查找主类名称的可移植方法,java,Java,有没有办法从JVM中运行的任意代码中找到用于启动当前JVM的主类的名称 所谓任意,我的意思是代码不一定在主线程中运行,或者可能在调用main之前就在主线程中运行(例如,用户提供的java.system.classloader中的代码,它在main之前运行,因为它用于加载main)-因此,检查调用堆栈是不可能的。这是我能得到的最接近的调用堆栈,您可以从这里获取它。我不能保证它是真正可移植的,如果任何方法调用另一个类的主方法,它将不起作用。如果您找到更干净的解决方案,请告诉我 import java

有没有办法从JVM中运行的任意代码中找到用于启动当前JVM的主类的名称


所谓任意,我的意思是代码不一定在主线程中运行,或者可能在调用main之前就在主线程中运行(例如,用户提供的java.system.classloader中的代码,它在main之前运行,因为它用于加载main)-因此,检查调用堆栈是不可能的。

这是我能得到的最接近的调用堆栈,您可以从这里获取它。我不能保证它是真正可移植的,如果任何方法调用另一个类的主方法,它将不起作用。如果您找到更干净的解决方案,请告诉我

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;
    }
}
import java.util.Map.Entry;
公共类TestMain{
/**
*@param args
*@ClassNotFoundException
*/
公共静态void main(字符串[]args)引发ClassNotFoundException{
System.out.println(findMainClass());
}
公共静态字符串findMainClass()引发ClassNotFoundException{
对于(条目:Thread.getAllStackTraces().entrySet()){
Thread Thread=entry.getKey();
if(thread.getThreadGroup()!=null&&thread.getThreadGroup().getName().equals(“main”)){
对于(StackTraceElement StackTraceElement:entry.getValue()){
if(stackTraceeElement.getMethodName().equals(“main”)){
试一试{
Class c=Class.forName(stackTraceeElement.getClassName());
类[]argTypes=新类[]{String[].Class};
//如果主方法是假的,这将抛出NoSuchMethodException
c、 getDeclaredMethod(“主”,argTypes);
返回stackTraceeElement.getClassName();
}捕获(无此方法例外){
e、 printStackTrace();
}
}
}
}
}
返回null;
}
}

在JVM上,首先调用主类的main方法。(另请参阅)那么,“可能在调用main之前就已经在主线程中运行”是什么意思呢。我想这个短语提到了“静态初始值设定项”或“线程运行()”@cocoatomo:我遗漏了一些东西。该链接是否显示了原始海报问题的解决方案?如果是的话,尽管我已经看过了,但不知怎么的,我还是错过了。@Hovercraft满是鳗鱼:对不起,我在完成我的评论之前误按了返回键。我想了解BeeOnRope的意图,因此我将确保BeeOnRope希望满足的条件。JLS可能会这么说,但实际上并非如此。主类必须由类加载器加载,而该类加载器本身就是一个对象,其类必须在主类之前加载。典型的类加载器实现,如URLClassLoader,在其实现中会使用大量其他类,这些类也会在main之前加载。如果您编写自己的类加载器,并通过指定java.system.class.loader属性将其安装为系统类加载器,则很容易看出这一点。谢谢,我知道此方法,但不幸的是,它不适用于我,因为在加载包含main的类之前,它也需要工作(请参阅添加到类加载器问题中的我的注释).无论如何都要接受它,因为它做了正确的事情,如果我愿意推迟我需要基于主类所做的工作,我可以使用它。顺便说一句,如果你想避免更多误报,我认为您可以查看调用main的类,并验证它是否是预期的特定于JDK的类-尽管这会引入对特定JDK或JDK的依赖。