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?

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

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


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.


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


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.