2016-07-27 22 views
5

Ich habe ein Programm geschrieben, das einen Verwendungshinweis ausgibt. Es gibt zur Zeit den Pfad zur Hauptdatei jar zurück, wie ursprünglich in der Befehlszeile eingegeben wurde.Wie wird der Pfad zum aktuell ausgeführten Java-Befehlszeilenpfad abgerufen? (vor symbolischen Links)

Usage: java -jar path/to/MyJar.jar <params> ... 

Der Vollständigkeit halber möchte ich sicherstellen möchten, dass die java Bit als auch Echo zurück, wie es verschiedene Möglichkeiten sind java zuzugreifen, (mehr als nur das Wort java und kürzer als der kanonische Weg zu /us/opt/java-1.8.0-u123/bin/java)

Usage: /us/opt/java7/bin/java -jar MyJar.jar <params> ... 
Usage: ./bin/java -jar MyJar.jar <params> ... 
Usage: java -jar MyJar.jar <params> ... 
# whatever the user typed in 

Wie kann ich bestimmen, welche Befehlszeile verwendet, um die JVM zu evozieren?
Ich möchte den ursprünglichen Befehlszeilenwert vor der Auswertung symbolischer Links.

Ich verwende nicht System.getProperty("java.home"), weil es keinen Respekt vor dem ursprünglichen Befehlszeilenwert hat, nur die endgültige 'kanonische' Position der JVM. (Ein Hinweis zur Verwendung wie Usage: /us/opt/java-1.8.0-u123/jre/bin/java -jar ... wäre ziemlich ausführlicher Having,
insbesondere bei Verwendung von einfachen java auf der Kommandozeile.)

ist die Bestimmung die Befehlszeilen Lage von java möglich unter Verwendung von reinem Java-Code?

+0

Mögliches Duplikat von [Ermitteln des Speicherorts der JVM-Programmdatei zur Laufzeit] (http: // stackoverf low.com/questions/3392416/determining-location-of-jvm-executable-during-runtime) – ipsi

+0

Ich frage mich, warum der Downvote. Liegt es daran, dass die Frage unklar ist oder weil sie doppelt ist? Ich habe gesucht, bevor ich gefragt habe, aber ich habe immer Ergebnisse erhalten, die diese spezielle Frage nicht gelöst haben. –

+0

Es ist nicht sofort klar, dass Sie sich der anderen Optionen bewusst waren oder was Sie zu tun versuchen, was Sie mit der Antwort mit der höchsten Wahl in der verknüpften Frage nicht tun können. – ipsi

Antwort

0

Verwenden folgenden Befehl ein (das heißt nicht ein Wrapper-Skript in bash mit)

jps -mlvV 

Dies alles über das Ausführen von Java-Prozesse gedruckt werden soll.

Wo als ps -e sollten Sie ausführbaren Pfad geben.

Folgendes ist reine Java-Lösung, es druckt nicht den eigentlichen Befehl zum Ausführen der Anwendung, aber es erzeugt einen Befehl, der den gleichen Effekt haben wird.

import java.io.File; 
import java.lang.management.ManagementFactory; 
import java.util.List; 
import java.util.Map.Entry; 
import java.util.stream.Collectors; 

public class Main { 
    public static void main(String[] args) { 
     System.out.println("Printing command"); 
     createCommand(); 
    } 
    public static void createCommand() { 
     try { 
      String jvm = getJvmExecutable(); 
      String mainClassName = findMainClass(); 
      String processDir = System.getProperty("user.dir"); 


      String arguments = getArguments(); 
      String classpath = ManagementFactory.getRuntimeMXBean().getClassPath(); 


      String command = String.format("cd %s & %s %s -classpath %s %s",processDir, jvm, arguments, classpath, mainClassName); 

      System.out.println(command); 
     } catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

    private static String getJvmExecutable() { 
     String jvm = ""; 
     jvm = System.getProperty("java.home"); 
     jvm += File.separator + "bin" + File.separator + "java"; 
     jvm = '"' + jvm + '"'; 
     return jvm; 
    } 

    private static String getArguments() { 
     List<String> argsList = ManagementFactory.getRuntimeMXBean().getInputArguments(); 
     String args = argsList.stream().collect(Collectors.joining(" ")); 

     return args; 
    } 

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

Hinweis: Es wird mit einfachen Java-Projekten oder normalen JARS arbeiten, aber es wird nicht mit speziellem Classloading wie IST, OSGI oder Frühling Stiefels ist Classloading arbeiten.

Ich benutzte die findMainClass() Methode aus dieser Antwort https://stackoverflow.com/a/8275751/5343269

+0

Ich bin auf der Suche nach einer reinen Java-Code-Lösung, so dass die Anwendung ein eigenes Verwendungsskript generieren kann. Es scheint ineffizient zu sein, zu diesem Zweck einen externen Prozess wie "jps" oder "ps" auszuführen. –

+0

Code für Java-Lösung hinzugefügt. – 11thdimension

+0

Ich klärte die Frage. Ich habe bereits den Weg zur Hauptklasse und zu meinem Krug, aber was ich suche, ist ein Weg zu Java, der nicht so knapp ist. Wenn der Benutzer also 'java' eintippt, kann die Verwendungsnotiz einfach' java' sein. Wenn der Benutzer einen symbolischen Link eingegeben hat, möchte ich das nur. Ich möchte * nicht * immer * den vollständigen Pfad anzeigen, wie er von 'System.getProperty (" java.home ") zurückgegeben wird. –

0

Verwenden Sie diese Systemeigenschaft in Code

System.getProperty("java.home"); 

Das Installationsverzeichnis für Java Runtime Environment (JRE)

Mehr Infos here

zurück
+1

Ich habe die Frage geklärt. Diese Antwort funktioniert nicht für mich. –