Comment obtenir des arguments VM à partir de l'application Java?

162

Je dois vérifier si une option qui peut être passée à JVM est explicitement définie ou a sa valeur par défaut.

Pour être plus précis: je dois créer un thread spécifique avec une taille de pile native plus élevée que celle par défaut, mais au cas où l'utilisateur voudrait s'occuper de ces choses par lui-même en spécifiant l' -Xssoption Je veux créer tous les threads avec la taille de pile par défaut (qui sera spécifié par l'utilisateur dans l'option -Xss).

J'ai vérifié des classes comme java.lang.Systemet java.lang.Runtime, mais celles-ci ne me donnent aucune information utile sur les arguments de VM.

Existe-t-il un moyen d'obtenir les informations dont j'ai besoin?

okutane
la source

Réponses:

183

Avec ce code, vous pouvez obtenir les arguments JVM:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
David Schuler
la source
Malheureusement, vous ne pouvez pas obtenir le nom de la classe principale s'il est indiqué sur la ligne de commande.
Daniel
@Daniel, cela devrait vous donner le nom de la classe principale: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz
3
Si vous êtes assuré d'être en cours d'exécution sur la JVM d'Oracle et que vous avez le code pour analyser les arguments qui peuvent être utiles.
laz
2
@Vulcan Cela n'obtient pas d'arguments VM. Il contient le nom de la classe principale et le tableau args de la méthode principale.
dacongy
@dacongy Je n'ai jamais laissé entendre que les arguments VM sont situés dans la sun.java.commandpropriété système; J'ai dit que la propriété peut être utilisée pour acquérir le nom de la classe principale (bien que je n'ai pas mentionné, comme @laz l'a souligné, cette propriété n'est présente que sur la JVM d'Oracle).
FThompson
207

Au démarrage, passez ceci -Dname=value

puis dans votre code, vous devez utiliser

value=System.getProperty("name");

pour obtenir cette valeur

Java_Freak
la source
4
Je ne peux pas utiliser ceci pour obtenir -Xdebug
petertc
20
Je ne sais pas pourquoi cette réponse a été si votée, cela ne récupère que les paramètres d'application (spécifiés avec -D), pas les paramètres VM (ceux spécifiés avec -X). La question concerne spécifiquement les paramètres -X.
cleberz
5
Je suis venu ici parce que je croyais que les paramètres de type -Dname=valuesont des arguments JVM et qu'il n'y a pas de différence intrinsèque aux -Xarguments. En fait, ils sont tous deux passés à java et non à l'application en ligne de commande et comme preuve par exemple, dans maven, vous pouvez passer les deux en tant que -Drun.jvmArguments=.... Je crois que c'est pourquoi il est voté pour.
kap
Cela ne répond pas du tout aux besoins des affiches originales.
dan.m était l'utilisateur2321368 le
4
Pourrait être ! mais il google sur le dessus lors de la recherche de "comment lire les options de VM dans le code" et c'est pourquoi c'est pertinent)
62mkv
4

J'ai trouvé que HotSpot répertorie tous les arguments VM dans le bean de gestion à l'exception de -client et -server. Ainsi, si vous déduisez l'argument -client / -server du nom de la VM et que vous l'ajoutez à la liste du bean de gestion d'exécution, vous obtenez la liste complète des arguments.

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

Peut être raccourci si vous voulez les arguments dans un fichier List<String>.

Note finale: Nous pourrions également vouloir étendre cela pour gérer le cas rare d'avoir des espaces dans les arguments de ligne de commande.

Stefan Reich
la source
Ouais, je viens de le faire. Cheers :)
Stefan Reich
2

Je n'ai pas essayé d'obtenir spécifiquement les paramètres de la VM, mais il y a une mine d'informations dans les utilitaires JMX, en particulier les utilitaires MXBean. Ce serait là que je commencerais. J'espère que vous y trouverez quelque chose pour vous aider.

Le site Web du soleil a un tas de technologies:

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

recycle
la source
0

Si vous voulez la ligne de commande entière de votre processus java, vous pouvez utiliser: JvmArguments.java (utilise une combinaison de JNA + / proc pour couvrir la plupart des implémentations Unix)

user2179737
la source