2008-09-03 7 views
51

Gibt es eine Möglichkeit, den Namen des Programms zu finden, das in Java ausgeführt wird? Die Klasse der Hauptmethode wäre gut genug.

Antwort

45

Versuchen Sie folgendes:

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

Natürlich funktioniert dies nur, wenn Sie von der Haupt-Thread laufen. Leider glaube ich nicht, dass es eine Systemeigenschaft gibt, die Sie abfragen können, um das herauszufinden.

Edit: Pulling in @John Meagher Kommentar, das ist eine großartige Idee:

Um sich zu erweitern @jodonnell Sie können auch bekommen alle Stack-Traces im System mit Thread.getAllStackTraces() . Von können Sie alle Stapel Traces für den "Haupt" Thread nach durchsuchen, was die Hauptklasse ist. Diese funktioniert auch, wenn Ihre Klasse nicht im Hauptthread ausgeführt wird.

+0

Guten Trick. Im Allgemeinen würde man dies von main() aus nennen, daher gibt es an dieser Stelle nur einen Thread, aber falls dieser von woanders aufgerufen wird, haben wir besser dieses Thread-Problem im Hinterkopf ... – PhiLho

+4

Es gibt keine garantie main thead to ausgeführt werden, wenn Sie versuchen, den App-Namen von anderen Threads zu finden. Der Haupt-Thread könnte normal enden und einige andere Hintergrund-Threads sind noch nicht beendet. Glaube nicht, dass es legitim ist, diesen Trick anders als vom Hauptthread aus zu machen. –

3

Auch über die Befehlszeile können Sie das Tool jps ausführen. Klingt wie ein

jps -l 

werden Sie bekommen, was Sie wollen.

15

Um @jodonnell zu erweitern, können Sie auch alle Stack-Traces im System mit Thread.getAllStackTraces() abrufen. Von diesem können Sie alle Stapelspuren für den main Thread durchsuchen, um festzustellen, was die Hauptklasse ist. Dies funktioniert auch dann, wenn Ihre Klasse nicht im Hauptthread ausgeführt wird.

+7

Es ist möglich, dass der Hauptthread nicht mehr ausgeführt wird, die Anwendung jedoch weiterhin ausgeführt wird (andere Nicht-Daemon-Threads). Dies passiert wahrscheinlich in vielen GUI/Swing-Anwendungen, da das allgemeine Idiom ist, dass der Haupt-Thread auf EDT aufruft, um das erste Frame zu erzeugen und dann zu beenden. –

-5

Oder Sie könnten einfach getClass() verwenden. Sie können etwas tun wie:

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

Und dann wird PROGNAME überall innerhalb Foo verfügbar sein. Wenn Sie sich nicht in einem statischen Kontext sind, dann wird es leichter, wie Sie diese nutzen könnten:

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

Ich glaube nicht, dass dies das Problem löst. Das Poster weiß nicht, welche Klasse die 'main'-Methode enthält, die beim Starten von Java aufgerufen wurde (vielleicht ist es Teil einer Bibliothek eines Drittanbieters). –

+1

Das ergibt überhaupt keinen Sinn. Es funktioniert nur, wenn ich wüsste, dass 'Foo' die Hauptklasse ist. Aber dann müsste ich das nicht tun. – maaartinus

-3

Versuchen Sie folgendes:

Java-Klassen haben statische Instanz ihrer eigenen Klasse (Class-Typ) .

Das heißt, wenn wir eine Klasse namens Main haben. Dann können wir seine Klasseninstanz von Main.class

Wenn Sie nur dem Namen nach, dann interessiert sind erhalten,

String classname = Main.class.getName();

+0

Aber in diesem Fall wissen Sie nicht, welche Klasse die "Haupt" -Klasse ist. – ryantm

2

Für den Zugriff auf die Klassenobjekte, wenn Sie sich in einem statischen Kontext

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()); 
    } 
} 

Offensichtlich hier alle drei Anrufe

class ClassUtils 

zurück, aber Sie erhalten das Bild;

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

Dies ist der Code, den ich mit den kombinierten Antworten von Jodonnell und John Meagher entwickelt habe. Er speichert die Hauptklasse in einer statischen Variablen Aufwand für wiederholte Anrufe zu reduzieren:

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

Verifiziert auf JDK 1.7.0_07 – sourcedelica

+1

Ich glaube, das funktioniert nur auf der HotSpot VM. siehe http://java.dzone.com/articles/programmamatic-restart-java – ericsoco