¿Cómo obtener argumentos de VM desde el interior de la aplicación Java?

162

Necesito verificar si alguna opción que se puede pasar a JVM está establecida explícitamente o tiene su valor predeterminado.

Para ser más específico: necesito crear un hilo específico con un tamaño de pila nativo más alto que el predeterminado, pero en caso de que el usuario quiera encargarse de esas cosas por sí mismo especificando la -Xssopción Quiero crear todos los hilos con el tamaño de pila predeterminado (que será especificado por el usuario en la opción -Xss).

He verificado clases como java.lang.Systemy java.lang.Runtime, pero estas no me dan información útil sobre los argumentos de VM.

¿Hay alguna forma de obtener la información que necesito?

okutane
fuente

Respuestas:

183

Con este código puede obtener los argumentos de JVM:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();
David Schuler
fuente
Lamentablemente, no puede obtener el nombre de la clase principal si se proporciona en la línea de comando.
Daniel
@Daniel, esto debería darte el nombre de la clase principal: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz
3
Si se garantiza que se ejecutará en JVM de Oracle y tiene el código para analizar los argumentos que pueden ser útiles.
laz
2
@Vulcan Eso no obtiene argumentos de VM. Contiene el nombre de la clase principal y la matriz de argumentos del método principal.
dacongy
@dacongy Nunca he implicado que los argumentos de VM se encuentran en la sun.java.commandpropiedad del sistema; Dije que la propiedad se puede usar para adquirir el nombre de la clase principal (aunque no mencioné, como señaló @laz, esa propiedad solo está presente en la JVM de Oracle).
FThompson
206

Al inicio, pasa esto -Dname=value

y luego en tu código deberías usar

value=System.getProperty("name");

para obtener ese valor

Java_Freak
fuente
44
No puedo usar esto para obtener -Xdebug
petertc
20
No estoy seguro de por qué esta respuesta ha sido tan votada, esto solo recupera los parámetros de la aplicación (especificados con -D), no los parámetros de VM (aquellos especificados con -X). La pregunta es específicamente sobre -X params.
cleberz
44
Vine aquí porque creía que los parámetros de tipo -Dname=valueson argumentos JVM y que no hay diferencia intrínseca a los -Xargumentos. En realidad, ambos se pasan a Java y no a la aplicación en la línea de comando y, como prueba por ejemplo, en Maven puedes pasar ambos como -Drun.jvmArguments=.... Creo que es por eso que se vota.
kap
Esto no responde a las necesidades originales de los carteles.
dan.m fue user2321368 el
44
Puede ser ! pero busca en la parte superior cuando busca "cómo leer las opciones de VM en el código" y por eso es relevante)
62mkv
4

Descubrí que HotSpot enumera todos los argumentos de VM en el bean de administración, excepto -client y -server. Por lo tanto, si infiere el argumento -client / -server del nombre de la máquina virtual y lo agrega a la lista del bean de administración de tiempo de ejecución, obtendrá la lista completa de argumentos.

Aquí está el 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();
  }
}

Podría acortarse si desea los argumentos en a List<String>.

Nota final: También podríamos querer extender esto para manejar el caso raro de tener espacios dentro de los argumentos de la línea de comando.

Stefan Reich
fuente
Sí, acabo de hacerlo. Saludos :)
Stefan Reich
0

Si desea la línea de comando completa de su proceso java, puede usar: JvmArguments.java (usa una combinación de JNA + / proc para cubrir la mayoría de las implementaciones de Unix)

usuario2179737
fuente