Como obter argumentos da VM de dentro do aplicativo Java?


162

Preciso verificar se alguma opção que pode ser passada para a JVM está definida explicitamente ou tem seu valor padrão.

Para ser mais específico: preciso criar um encadeamento específico com tamanho de pilha nativo mais alto que o padrão, mas caso o usuário queira cuidar de tais coisas, especificando a -Xssopção Desejo criar todos os encadeamentos com tamanho de pilha padrão (que será especificado pelo usuário na opção -Xss).

Eu verifiquei classes como java.lang.Systeme java.lang.Runtime, mas elas não estão me fornecendo informações úteis sobre argumentos da VM.

Existe alguma maneira de obter as informações necessárias?

Respostas:


183

Com esse código, você pode obter os argumentos da JVM:

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

Infelizmente, você não pode obter o nome da classe principal se ele for fornecido na linha de comando.
Daniel

@ Daniel, isso deve te dar o nome da classe principal: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz

3
Se você tem garantia de estar executando na JVM da Oracle e tem o código para analisar os argumentos que podem ser úteis.
Laz

2
@ Vulcan Isso não obtém argumentos da VM. Ele contém o nome da classe principal e a matriz args para o método principal.
dacongy

@dacongy Nunca sugeri que os argumentos da VM estão localizados na sun.java.commandpropriedade do sistema; Eu disse que a propriedade pode ser usada para adquirir o nome da classe principal (embora eu não tenha mencionado, como o @laz apontou, essa propriedade está presente apenas na JVM da Oracle).
precisa saber é o seguinte

206

Na inicialização, passe isso -Dname=value

e então no seu código você deve usar

value=System.getProperty("name");

para obter esse valor


4
Eu não posso usar isso para obter -Xdebug
petertc

20
Não sei por que essa resposta foi tão votada, isso recupera apenas os parâmetros do aplicativo (especificados com -D), não os parâmetros da VM (aqueles especificados com -X). A pergunta é especificamente sobre parâmetros -X.
cleberz

4
Eu vim aqui porque acreditava que parâmetros do tipo -Dname=valuesão argumentos da JVM e que não há diferença intrínseca aos -Xargumentos. Na verdade, eles são passados ​​para java e não para o aplicativo na linha de comando e, como evidência por exemplo, no maven você pode passar os dois como -Drun.jvmArguments=.... Eu acredito que é por isso que é votado.
kap

Isso não responde às necessidades originais dos pôsteres.
precisa saber é o seguinte

4
Pode ser ! mas fica no topo quando pesquisa "como ler opções de VM no código" e é por isso que é relevante)
62mkv

4

Descobri que o HotSpot lista todos os argumentos da VM no bean de gerenciamento, exceto -client e -server. Portanto, se você inferir o argumento -client / -server a partir do nome da VM e adicioná-lo à lista do bean de gerenciamento de tempo de execução, obterá a lista completa de argumentos.

Aqui está o 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();
  }
}

Pode ser reduzido se você quiser os argumentos em a List<String>.

Nota final: também podemos estender isso para lidar com o caso raro de ter espaços nos argumentos da linha de comando.


Sim, acabou. Cheers :)
Stefan Reich


0

Se você quiser toda a linha de comandos do seu processo java, poderá usar: JvmArguments.java (usa uma combinação de JNA + / proc para cobrir a maioria das implementações unix)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.