Cinco coisas que você não sabia sobre ... os sinalizadores de linha de comando para JVM

Ajuste com exatidão o desempenho da JVM e o Java runtime

As Java™ virtual machines possuem centenas de opções de linha de comando que os desenvolvedores de Java mais experientes podem usar para ajustar o Java runtime. Saiba como monitorar e registrar o desempenho do compilador, desativar a coleta de lixo explícita (System.gc();), estender o JRE e mais.

Ted Neward, Principal, Neward & Associates

Ted Neward는 글로벌 컨설팅 업체인 ThoughtWorks의 컨설턴트이자 Neward & Associates의 회장으로 Java, .NET, XML 서비스 및 기타 플랫폼에 대한 컨설팅, 조언, 교육 및 강연을 한다. 워싱턴 주의 시애틀 근교에 살고 있다.



24/Ago/2010

Sobre esta série

Você acha que sabe programação Java? A verdade é que a maioria dos desenvolvedores tem apenas algum conhecimento sobre a plataforma Java, aprendendo o suficiente para concluir a tarefa. Nesta série, Ted Neward examina a fundo a funcionalidade da plataforma Java para revelar fatos pouco conhecidos que podem ajudar você a superar até mesmo os desafios de programação mais difíceis.

A JVM é que faz o trabalho duro por trás da funcionalidade e do desempenho do aplicativo Java que a maioria dos desenvolvedores Java considera natural. E ainda assim pouquíssimos profissionais na área realmente entendem como a JVM faz o que ela faz — coisas como alocar e definir objetos de coleta de lixo, prolongar encadeamentos, abrir e fechar arquivos, interpretar e/ou executar compilação JIT para bytecode Java e mais.

A falta de familiaridade com a JVM não somente ocasiona perdas em termos de desempenho do aplicativo, como também quando algo vai mal com a JVM, pode ser muito difícil corrigir.

Este capítulo da série cinco coisas apresenta um útil sinalizador de JVM de linha de comando que você pode usar para diagnosticar e ajustar o desempenho de sua Java virtual machine.

1. DisableExplicitGC

Eu perdi a conta de quantas vezes fui solicitado a realizar uma consultoria sobre um problema de desempenho de aplicativo, de quantas vezes executei um grep rápido no código e descobri o que é mostrado na Listagem 1 — o antipadrão de desempenho Java original:

Listagem 1. System.gc();
// We just released a bunch of objects, so tell the stupid
// garbage collector to collect them already!
System.gc();

A coleta de lixo explícita é uma ideia realmente ruim,— algo como estar preso em uma cabine telefônica com um pit bull raivoso. Embora a semântica exata da chamada dependa da implementação, supondo-se que a JVM esteja executando um coletor de lixo de geração (o que é a maioria deles), System.gc(); força a VM a realizar uma "varredura completa" do heap, mesmo que não seja necessário. As varreduras completas são, de modo geral, muitas vezes mais caras do que uma operação de GC regular, que é apenas matemática simples ineficiente.

Mas não acredite muito nisso — os engenheiros da Sun nos forneceram um sinalizador de JVM somente para este problema de erro humano em particular: o sinalizador -XX:+DisableExplicitGC automaticamente transforma uma chamada de System.gc() em uma no-op, oferecendo-lhe a oportunidade de executar seu código e você mesmo constatar se o System.gc() ajudou ou prejudicou a execução geral da JVM.


2. HeapDumpOnOutOfMemoryError

Você já passou por situações em que a JVM apresentou problemas, emitindo mensagens do tipo OutOfMemoryError, e não conseguiu configurar o depurador para capturar o erro e verificar qual era o problema? Problemas esporádicos e/ou sem possibilidade de determinação como esse podem deixar um desenvolvedor completamente maluco.

Caveat emptor

Nem todos os sinalizadores de linha de comando são necessariamente suportados por qualquer VM, exceto os da Sun/Oracle. A melhor maneira de descobrir se um sinalizador é suportado é experimentá-lo e ver se funciona, é claro. Entretanto, como esses sinalizadores são tecnicamente não suportados, é você quem assume toda a responsabilidade por usá-los. Nem eu, a Sun/Oracle e a IBM® seremos responsáveis caso qualquer um desses sinalizadores prejudiquem seu código, seus dados, seu servidor ou qualquer outra coisa. Por precaução, eu o aconselho experimentá-los primeiro em um ambiente virtual (de não produção).

O que você deseja em momentos como esse é obter uma captura instantânea do heap exatamente quando a JVM estiver entrando em colapso — e isso é exatamente o que o comando -XX:+HeapDumpOnOutOfMemoryError faz.

A execução desse comando diz à JVM para obter uma "captura instantânea do dump do heap" e salvá-lo em um arquivo para processamento, geralmente usando o utilitário jhat (que eu apresentei em um artigo anterior). É possível especificar o caminho real no qual o arquivo é salvo usando o sinalizador -XX:HeapDumpPath correspondente. (Independentemente de onde o arquivo for salvo, certifique-se de que o sistema de arquivos e/ou o processo Java tenha a configuração de permissão necessária para poder gravá-lo.)


3. bootclasspath

Periodicamente, é útil enviar uma classe para o caminho de classe que seja um pouco diferente do que acompanha o JRE comum ou do que de certa forma estende o JRE. (Um exemplo seria um novo provedor Java Crypto API). Se você quiser estender o JRE, será necessário que sua implementação customizada esteja disponível para o ClassLoader de autoinicialização, que carrega o java.lang.Object e todos os seus colegas no rt.jar.

Embora você pudesse abrir o rt.jar e inserir nele sua implementação customizada ou novo pacote, isso tecnicamente violaria a licença com a qual concordou quando transferiu o JDK por download.

Em vez disso, use a opção -Xbootclasspath da própria JVM, juntamente com -Xbootclasspath/p e -Xbootclasspath/a.

-Xbootclasspath permite que você configure o caminho de classe de boot completo, que geralmente tem que incluir uma referência para rt.jar, além de vários outros arquivos JAR que acompanham o JDK que não fazem parte do rt.jar. -Xbootclasspath/p acrescenta no início o valor do bootclasspath existente, e -Xbootclasspath/a o anexa no final.

Se, por exemplo, você tiver modificado o java.lang.Integercomum e colocar as modificações em um subdiretório, mods, um parâmetro -Xbootclasspath/a mods colocará o novo número inteiro na frente do valor padrão.


4. verbose

-verbose é um importante utilitário de diagnóstico para praticamente qualquer tipo de aplicativo Java. O sinalizador possui três subsinalizadores:gc, class e jni.

gc geralmente é o primeiro lugar que os desenvolvedores verificam para tentar descobrir se o coletor de lixo da JVM está falhando e provocando o desempenho insatisfatório. Infelizmente, interpretar a saída de gc pode ser complicado — tanto é que isso tem sido assunto de livros inteiros. E ainda pior, a saída impressa da linha de comando pode mudar de um release Java para outro ou de uma JVM para outra, dificultando ainda mais a interpretação correta.

Falando de modo geral, se o coletor de lixo for um coletor de geração (o que a maioria das VMs de "classe corporativa" é), algum tipo de sinalizador visível aparecerá para indicar a passagem do GC de varredura completa; na JVM Sun, o sinalizador aparece como "[Full GC ...]" no início da linha de saída do GC.

class pode ser uma solução para tentar diagnosticar conflitos de ClassLoader e/ou de classe incompatível. Ele relata não somente quando uma classe é carregada, mas também de onde a classe foi carregada, incluindo o caminho para o arquivo JAR, supondo que ela venha de um JAR.

jni é de pouco uso, exceto ao se trabalhar com bibliotecas nativas e JNI. Quando ativado, ele relatará vários eventos JNI, como quando as bibliotecas nativas são carregadas e quando os métodos são ligados; novamente, a saída pode variar de um release ou JVM para outro.


5. -X de linha de comando

Eu listei algumas de minhas opções de linha de comando favoritas que a JVM oferece, mas há tantas outras que você mesmo poderá descobrir. A execução do argumento de linha de comando -X lista todos os argumentos não padrão (mas muito seguros) que a JVM oferece— coisas como:

  • -Xint, que executa a JVM no modo interpretado (que pode ser útil para testar se o compilador JIT está realmente afetando seu código ou verificando se o compilador JIT tem algum erro).
  • -Xloggc:, que faz a mesma coisa que -verbose:gc mas registra em um arquivo em vez de emitir na janela de linha de comando.

As opções da linha de comando JVM são alteradas periodicamente, portanto, verificá-las ocasionalmente é uma boa ideia. Isso pode representar a diferença entre passar a noite em frente ao monitor ou ir para casa às 17h, jantar com a esposa e filhos (ou massacrar seus inimigos no Mass Effect 2, dependendo de sua preferência).


Conclusão

Os sinalizadores de linha de comando não são indicados para uso permanente em um ambiente de produção — na verdade, com exceção dos sinalizadores que você (pode) acabar usando para ajustar o coletor de lixo da JVM, nenhum sinalizador de linha de comando não padrão é realmente indicado para uso na produção. Mas como ferramentas para examinar os trabalhos internos da máquina virtual completamente obscura eles são de grande valia.

A seguir, na série cinco coisas: Ferramentas Java de todos os dias.

Recursos

Aprender

Discutir

  • Envolva-se com a comunidade do My developerWorks. Conecte-se com outros usuários do developerWorks enquanto explora os blogs, fóruns, grupos e wikis conduzidos por desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Tecnologia Java, Software livre
ArticleID=525197
ArticleTitle=Cinco coisas que você não sabia sobre ... os sinalizadores de linha de comando para JVM
publish-date=08242010