2008-09-03 15 views
51

¿Hay alguna forma de encontrar el nombre del programa que se ejecuta en Java? La clase del método principal sería lo suficientemente buena.

Respuesta

45

Prueba esto:

StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
    StackTraceElement main = stack[stack.length - 1]; 
    String mainClass = main.getClassName(); 

Por supuesto, esto sólo funciona si se está ejecutando desde el hilo principal. Lamentablemente, no creo que haya una propiedad del sistema que pueda consultar para descubrirlo.

Editar: Tirando en el comentario de @ John Meagher, que es una gran idea:

Para ampliar @jodonnell también puede obtener todos los seguimientos de pila en el sistema usando Thread.getAllStackTraces() . Desde esto puede buscar todas las trazas de la pila para el subproceso "principal" al determinar cuál es la clase principal. Este funcionará incluso si su clase no está ejecutándose en el hilo principal.

+0

buen truco. En general, uno llamaría esto desde main(), por lo que solo hay un hilo en este punto, pero en caso de que se llame desde otro lugar, es mejor que tengamos este problema en el hilo ... – PhiLho

+4

No hay ninguna garantía principal para se ejecutará cuando intente encontrar el nombre de la aplicación de otros hilos. El hilo principal podría terminar normalmente y algunos otros hilos de fondo aún no terminados. No creas que es legítimo hacer este truco distinto del hilo principal. –

3

También desde la línea de comandos puede ejecutar la herramienta jps. Suena como un

jps -l 

le conseguirá lo que quiere.

15

Para ampliar en @jodonnell también puede obtener todos los rastros de pila en el sistema usando Thread.getAllStackTraces(). A partir de esto, puede buscar todas las trazas de pila para el subproceso main para determinar cuál es la clase principal. Esto funcionará incluso si su clase no se ejecuta en el hilo principal.

+7

Es posible que el hilo principal deje de ejecutarse pero la aplicación continúa (otros hilos que no son daemon). Esto probablemente ocurra en muchas aplicaciones GUI/Swing ya que la expresión común es para que el hilo principal invoque en EDT para crear el primer cuadro y luego terminar. –

-5

O simplemente podría usar getClass(). Puede hacer algo como:

public class Foo 
{ 
    public static final String PROGNAME = new Foo().getClass().getName(); 
} 

Y luego PROGNAME estará disponible en cualquier lugar dentro de Foo. Si no estás en un contexto estático, se hace más fácil que usted podría utilizar esto:

String myProgramName = this.getClass().getName(); 
+0

No creo que esto resuelva el problema. El póster no sabe qué clase contiene el método 'main' que se invocó cuando se inició Java (quizás es parte de una biblioteca de terceros). –

+1

Esto no tiene ningún sentido. Solo funciona si sabía que 'Foo' era la clase principal. Pero entonces no necesitaría hacer esto. – maaartinus

-3

Prueba esto:

clases

Java tienen instancia estática de su propia clase (tipo java.lang.Class) .

Eso significa que si tenemos una clase llamada Principal. entonces podemos obtener su instancia de clase por Main.class

Si usted está interesado en el nombre sólo entonces,

cadena className = Main.class.getName();

+0

Pero en este caso no sabes qué clase es la clase "principal". – ryantm

2

Para el acceso a los objetos de la clase cuando se está en un contexto estático

public final class ClassUtils { 
    public static final Class[] getClassContext() { 
     return new SecurityManager() { 
      protected Class[] getClassContext(){return super.getClassContext();} 
     }.getClassContext(); 
    }; 
    private ClassUtils() {}; 
    public static final Class getMyClass() { return getClassContext()[2];} 
    public static final Class getCallingClass() { return getClassContext()[3];} 
    public static final Class getMainClass() { 
     Class[] c = getClassContext(); 
     return c[c.length-1]; 
    } 
    public static final void main(final String[] arg) { 
     System.out.println(getMyClass()); 
     System.out.println(getCallingClass()); 
     System.out.println(getMainClass()); 
    } 
} 

Obviamente aquí todas las 3 llamadas volverán

class ClassUtils 

pero se obtiene la imagen;

classcontext[0] is the securitymanager 
classcontext[1] is the anonymous securitymanager 
classcontext[2] is the class with this funky getclasscontext method 
classcontext[3] is the calling class 
classcontext[last entry] is the root class of this thread. 
8

Este es el código que se me ocurrió al usar las respuestas combinadas de jodonnell y John Meagher. Almacena la clase principal en una variable estática para reducir la sobrecarga de llamadas repetidas:

private static Class<?> mainClass; 

public static Class<?> getMainClass() { 
    if (mainClass != null) 
    return mainClass; 

    Collection<StackTraceElement[]> stacks = Thread.getAllStackTraces().values(); 
    for (StackTraceElement[] currStack : stacks) { 
    if (currStack.length==0) 
     continue; 
    StackTraceElement lastElem = currStack[currStack.length - 1]; 
    if (lastElem.getMethodName().equals("main")) { 
     try { 
     String mainClassName = lastElem.getClassName(); 
     mainClass = Class.forName(mainClassName); 
     return mainClass; 
     } catch (ClassNotFoundException e) { 
     // bad class name in line containing main?! 
     // shouldn't happen 
     e.printStackTrace(); 
     } 
    } 
    } 
    return null; 
} 
16
System.getProperty("sun.java.command") 
+0

verificado en JDK 1.7.0_07 – sourcedelica

+1

Creo que esto solo funciona en la máquina virtual de HotSpot. ver http://java.dzone.com/articles/programmatically-restart-java – ericsoco

Cuestiones relacionadas