Wie bekomme ich VM-Argumente aus einer Java-Anwendung heraus?

162

Ich muss überprüfen, ob eine Option, die an JVM übergeben werden kann, explizit festgelegt ist oder ihren Standardwert hat.

Genauer gesagt: Ich muss einen bestimmten Thread mit einer höheren nativen Stapelgröße als der Standardstapel erstellen. Falls der Benutzer sich jedoch selbst um solche Dinge kümmern möchte, geben Sie die -XssOption an, mit der ich alle Threads mit der Standardstapelgröße erstellen möchte (Dies wird vom Benutzer in der Option -Xss angegeben).

Ich habe Klassen wie java.lang.Systemund überprüft java.lang.Runtime, aber diese geben mir keine nützlichen Informationen zu VM-Argumenten.

Gibt es eine Möglichkeit, die benötigten Informationen zu erhalten?

okutane
quelle

Antworten:

183

Mit diesem Code können Sie die JVM-Argumente erhalten:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
David Schuler
quelle
Leider können Sie den Namen der Hauptklasse nicht erhalten, wenn er in der Befehlszeile angegeben wird.
Daniel
@ Daniel, dies sollte Ihnen den Namen der Hauptklasse geben: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
Laz
3
Wenn Sie garantiert auf der JVM von Oracle ausgeführt werden und über den Code verfügen, um die Argumente zu analysieren, die nützlich sein können.
Laz
2
@Vulcan Das bekommt keine VM-Argumente. Es enthält den Namen der Hauptklasse und das Array args für die Hauptmethode.
Dacongy
@dacongy Ich habe nie angedeutet, dass sich VM-Argumente in der sun.java.commandSystemeigenschaft befinden. Ich sagte, dass die Eigenschaft verwendet werden kann, um den Namen der Hauptklasse zu erhalten (obwohl ich nicht erwähnt habe, wie @laz hervorhob, dass die Eigenschaft nur in der JVM von Oracle vorhanden ist).
FThompson
206

Übergeben Sie dies beim Start -Dname=value

und dann in Ihrem Code sollten Sie verwenden

value=System.getProperty("name");

um diesen Wert zu bekommen

Java_Freak
quelle
4
Ich kann dies nicht verwenden, um -Xdebug
petertc
20
Sie sind sich nicht sicher, warum diese Antwort so positiv bewertet wurde. Dadurch werden nur Anwendungsparameter (mit -D angegeben) und keine VM-Parameter (mit -X angegeben) abgerufen. Die Frage bezieht sich speziell auf -X-Parameter.
Cleberz
4
Ich bin hierher gekommen, weil ich glaubte, dass Parameter vom Typ -Dname=valueJVM-Argumente sind und dass es keinen wesentlichen Unterschied zu -XArgumenten gibt. Tatsächlich werden beide an Java und nicht an die Anwendung in der Befehlszeile übergeben, und als Beispiel können Sie in maven beide als übergeben -Drun.jvmArguments=.... Ich glaube, deshalb wird es positiv bewertet.
Kap
Dies entspricht überhaupt nicht den Anforderungen der Originalplakate.
dan.m war user2321368
4
Könnte sein ! aber es googelt oben bei der Suche nach "wie man VM-Optionen im Code liest" und deshalb ist es relevant)
62mkv
4

Ich habe festgestellt, dass HotSpot alle VM-Argumente in der Management-Bean mit Ausnahme von -client und -server auflistet. Wenn Sie also das Argument -client / -server aus dem VM-Namen ableiten und dieses zur Liste der Laufzeitverwaltungs-Beans hinzufügen, erhalten Sie die vollständige Liste der Argumente.

Hier ist die SSCCE:

import java.util.*;
import java.lang.management.ManagementFactory;

class main {
  public static void main(final String[] args) {
    System.out.println(fullVMArguments());
  }

  static String fullVMArguments() {
    String name = javaVmName();
    return (contains(name, "Server") ? "-server "
      : contains(name, "Client") ? "-client " : "")
      + joinWithSpace(vmArguments());
  }

  static List<String> vmArguments() {
    return ManagementFactory.getRuntimeMXBean().getInputArguments();
  }

  static boolean contains(String s, String b) {
    return s != null && s.indexOf(b) >= 0;
  }

  static String javaVmName() {
    return System.getProperty("java.vm.name");
  }

  static String joinWithSpace(Collection<String> c) {
    return join(" ", c);
  }

  public static String join(String glue, Iterable<String> strings) {
    if (strings == null) return "";
    StringBuilder buf = new StringBuilder();
    Iterator<String> i = strings.iterator();
    if (i.hasNext()) {
      buf.append(i.next());
      while (i.hasNext())
        buf.append(glue).append(i.next());
    }
    return buf.toString();
  }
}

Könnte kürzer gemacht werden, wenn Sie die Argumente in a wollen List<String>.

Schlussbemerkung: Möglicherweise möchten wir dies auch erweitern, um den seltenen Fall von Leerzeichen in Befehlszeilenargumenten zu behandeln.

Stefan Reich
quelle
Ja, habe es gerade getan. Prost :)
Stefan Reich
2

Ich habe nicht versucht, die VM-Einstellungen speziell abzurufen, aber die JMX-Dienstprogramme enthalten eine Fülle von Informationen, insbesondere die MXBean-Dienstprogramme. Hier würde ich anfangen. Hoffentlich finden Sie dort etwas, das Ihnen hilft.

Die Sun-Website hat eine Menge über die Technologie:

http://java.sun.com/javase/6/docs/technotes/guides/management/mxbeans.html

reccles
quelle
0

Wenn Sie die gesamte Befehlszeile Ihres Java-Prozesses verwenden möchten , können Sie Folgendes verwenden : JvmArguments.java (verwendet eine Kombination aus JNA + / proc, um die meisten Unix-Implementierungen abzudecken)

user2179737
quelle