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?

okutane
fonte

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();
David Schuler
fonte
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

Java_Freak
fonte
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.

Stefan Reich
fonte
Sim, acabou. Cheers :)
Stefan Reich
2

Não tentei obter especificamente as configurações da VM, mas há muitas informações nos utilitários JMX, especificamente nos utilitários MXBean. Aqui seria onde eu começaria. Espero que você encontre algo para ajudá-lo.

O site da sun tem um monte de tecnologia:

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

reccles
fonte
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)

user2179737
fonte