Jak uzyskać argumenty VM z wnętrza aplikacji Java?

162

Muszę sprawdzić, czy jakaś opcja, którą można przekazać do JVM, jest jawnie ustawiona lub ma wartość domyślną.

Mówiąc dokładniej: muszę utworzyć jeden konkretny wątek z większym rodzimym rozmiarem stosu niż domyślny, ale na wypadek, gdyby użytkownik chciał sam zająć się takimi sprawami, określając -Xssopcję Chcę utworzyć wszystkie wątki z domyślnym rozmiarem stosu (co zostanie określone przez użytkownika w opcji -Xss).

Sprawdziłem klasy takie jak java.lang.Systemi java.lang.Runtime, ale nie dają mi one żadnych przydatnych informacji o argumentach VM.

Czy jest jakiś sposób na uzyskanie potrzebnych informacji?

okutan
źródło

Odpowiedzi:

183

Za pomocą tego kodu możesz uzyskać argumenty JVM:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
David Schuler
źródło
Niestety nie możesz uzyskać nazwy klasy głównej, jeśli jest podana w wierszu poleceń.
Daniel
@Daniel, to powinno dać ci nazwę głównej klasy: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz
3
Jeśli masz gwarancję, że korzystasz z JVM Oracle i masz kod do analizowania argumentów, które mogą być przydatne.
laz
2
@Vulcan To nie otrzymuje argumentów maszyny wirtualnej. Zawiera nazwę klasy głównej oraz tablicę args do metody main.
dacongy
@dacongy Nigdy nie sugerowałem, że argumenty VM znajdują się we sun.java.commandwłaściwości systemowej; Powiedziałem, że właściwość można wykorzystać do uzyskania nazwy klasy głównej (chociaż nie wspomniałem, jak wskazał @laz, ta właściwość jest obecna tylko w JVM Oracle).
FThompson
207

Przy starcie podaj to -Dname=value

a następnie w swoim kodzie powinieneś użyć

value=System.getProperty("name");

aby uzyskać tę wartość

Java_Freak
źródło
4
Nie mogę tego użyć, aby uzyskać -Xdebug
petertc
20
Nie jestem pewien, dlaczego ta odpowiedź została tak pozytywnie oceniona, to pobiera tylko parametry aplikacji (określone przez -D), a nie parametry VM (te określone przez -X). Pytanie dotyczy konkretnie parametrów -X.
cleberz
5
Przyszedłem tutaj, ponieważ uważałem, że parametry typu -Dname=valuesą argumentami JVM i że nie ma wewnętrznej różnicy między -Xargumentami. W rzeczywistości oba są przekazywane do java, a nie do aplikacji w wierszu poleceń i jako przykład w maven można przekazać oba jako -Drun.jvmArguments=.... Uważam, że dlatego jest głosowany za.
kap
To w ogóle nie odpowiada na potrzeby oryginalnych plakatów.
dan.m był user2321368
4
Może być ! ale jest na topie podczas wyszukiwania „jak odczytać opcje maszyny wirtualnej w kodzie” i dlatego jest to istotne)
62mkv
4

Odkryłem, że HotSpot wyświetla wszystkie argumenty maszyny wirtualnej w komponencie bean zarządzania, z wyjątkiem -client i -server. Tak więc, jeśli wywnioskujesz argument -client / -server z nazwy maszyny wirtualnej i dodasz go do listy komponentu bean zarządzania w czasie wykonywania, otrzymasz pełną listę argumentów.

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

Można skrócić, jeśli chcesz, aby argumenty w pliku List<String>.

Ostatnia uwaga: możemy również chcieć to rozszerzyć, aby obsłużyć rzadki przypadek spacji w argumentach wiersza poleceń.

Stefana Reicha
źródło
Tak, właśnie to zrobiłem. Pozdrawiam :)
Stefan Reich
2

Nie próbowałem konkretnie uzyskać ustawień maszyny wirtualnej, ale w narzędziach JMX jest mnóstwo informacji, szczególnie w narzędziach MXBean. To byłby punkt, w którym bym zaczął. Miejmy nadzieję, że znajdziesz tam coś, co ci pomoże.

Witryna Sun zawiera sporo informacji na temat technologii:

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

reccles
źródło
0

Jeśli chcesz mieć całą linię poleceń swojego procesu java, możesz użyć: JvmArguments.java (używa kombinacji JNA + / proc do obsługi większości implementacji unixowych)

user2179737
źródło