Come ottenere argomenti VM dall'interno dell'applicazione Java?


162

Devo verificare se alcune opzioni che possono essere passate a JVM sono esplicitamente impostate o hanno il loro valore predefinito.

Per essere più specifici: ho bisogno di creare un thread specifico con una dimensione dello stack nativa superiore a quella predefinita, ma nel caso in cui l'utente voglia occuparsi di tali cose da solo specificando l' -Xssopzione Voglio creare tutti i thread con dimensioni dello stack predefinite (che verrà specificato dall'utente nell'opzione -Xss).

Ho controllato classi come java.lang.Systeme java.lang.Runtime, ma queste non mi danno alcuna informazione utile sugli argomenti della VM.

C'è un modo per ottenere le informazioni di cui ho bisogno?

Risposte:


183

Con questo codice è possibile ottenere gli argomenti JVM:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();

Purtroppo non è possibile ottenere il nome della classe principale se viene fornito sulla riga di comando.
Daniel,

@Daniel, questo dovrebbe darti il ​​nome della classe principale: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz

3
Se sei sicuro di essere in esecuzione sulla JVM di Oracle e disponi del codice per analizzare gli argomenti che possono essere utili.
Laz

2
@Vulcan Che non ottiene argomenti VM. Contiene il nome della classe principale e l'array args per il metodo principale.
dacongy,

@dacongy Non ho mai implicato che gli argomenti VM si trovino nella sun.java.commandproprietà di sistema; Ho detto che la proprietà può essere utilizzata per acquisire il nome della classe principale (anche se non ho menzionato, come sottolineato da @laz, che la proprietà è presente solo sulla JVM di Oracle).
FThompson,

207

All'avvio passare questo -Dname=value

e poi nel tuo codice dovresti usare

value=System.getProperty("name");

per ottenere quel valore


4
Non posso usare questo per ottenere -Xdebug
petertc

20
Non so perché questa risposta sia stata così votata, questo recupera solo i parametri dell'applicazione (specificati con -D), non i parametri VM (quelli specificati con -X). La domanda riguarda in particolare i parametri -X.
Cleberz,

5
Sono venuto qui perché credevo che i parametri di tipo -Dname=valuefossero argomenti JVM e che non vi fosse alcuna differenza intrinseca negli -Xargomenti. In realtà, entrambi vengono passati a Java e non all'applicazione dalla riga di comando e, come prova dell'esempio, in Maven puoi passare entrambi come -Drun.jvmArguments=.... Credo sia per questo che è stato votato.
Kap

Questo non risponde affatto alle esigenze dei poster originali.
dan.m era user2321368 il

4
Potrebbe essere ! ma cerca su Google quando si cerca "come leggere le opzioni della macchina virtuale nel codice" ed è per questo che è rilevante)
62mkv

4

Ho scoperto che HotSpot elenca tutti gli argomenti VM nel bean di gestione ad eccezione di -client e -server. Pertanto, se si deduce l'argomento -client / -server dal nome della VM e si aggiunge all'elenco del bean di gestione runtime, si ottiene l'elenco completo degli argomenti.

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

Potrebbe essere ridotto se si desidera che gli argomenti in a List<String>.

Nota finale: potremmo anche voler estendere questo per gestire il raro caso di avere spazi all'interno degli argomenti della riga di comando.


Sì, l'ho appena fatto. Saluti :)
Stefan Reich,


0

Se vuoi l'intera riga di comando del tuo processo java, puoi usare: JvmArguments.java (usa una combinazione di JNA + / proc per coprire la maggior parte delle implementazioni unix)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.