As ferramentas cobertas neste artigo são as mais utilizadas no ambiente Java e de grande utilidade para os desenvolvedores. Todas elas estão incorporadas à plataforma, não necessitando de nenhum pacote adicional.

Elas são invocadas por linha de comando, independente do ambiente de produção e você pode encontrá-las na pasta bin. São elas:

  • javac -é utilizada na compilação dos programas Java e normalmente já é gerenciada nas IDEs de forma transparente para o usuário;
  • java - é quem inicia a JVM e executa um programa Java. Diversos parâmetros estão disponíveis para a java, incluindo a configuração de propriedades, execução de programas em outros classpaths, seleção da JIT e tamanho do heap;
  • jar - é responsável por manipular os pacotes JAR, podendo assim criá-los, extraí-los, indexá-los, entre outras funcionalidades;
  • javadoc -ajuda o desenvolvedor na criação de uma documentação completa do software. Dentre as suas facilidades estão a extração da documentação automaticamente para uma série de formatos, escolha dos tipos de saídas e configuração do classpath a ser utilizado;
  • jdeps - é uma ferramenta de análise estática que ajuda o desenvolvedor a descobrir quais são as dependências existentes para os pacotes ou para as classes do software. Essa ferramenta pode ser extremamente útil nos casos em que não existe uma matriz de rastreabilidade para um código criado por outra empresa ou desenvolvedor;
  • jps - fornece uma lista de processos ativos na JVM, que ajuda os desenvolvedores a descobrirem os quais estão sendo executados em determinada máquina, quais recursos estão sendo consumidos e quais processos estão inativos e poderiam assim ser retirados de uma máquina;
  • jstat - exibe as estatísticas básicas sobre um determinado processo, podendo ajudar aos desenvolvedores e a equipe de infraestrutura a estudar o comportamento de determinados processos em certas condições, inclusive ajudar a determinar se um processo está com um comportamento normal;
  • jstatd - gera informações sobre as JVMs locais, o que também pode ajudar na identificação de determinados comportamentos da JVM e dos processos sobre ela no ambiente local;
  • jinfo - é outra ferramenta que permite uma melhor análise da JVM;
  • jstack e jmap - também ajudam na análise dos processos Java, permitindo a identificação de deadlocks e a quantidade de memória consumida pelos processos;
  • javap - é um descompilador Java bastante útil nos casos em que o desenvolvedor perdeu um código-fonte e deseja obtê-lo novamente, ou então para um desenvolvedor que gostaria de entender melhor o funcionamento de um determinado código, desde que possua a devida permissão para isso.

Além destas também será vista a ferramenta gráfica VisualVM, que compõe boa parte das ferramentas de linha de comando, porém exibe os resultados graficamente.

Vamos estudar cada uma delas e os recursos que as acompanham.

Ferramenta javac

É uma das mais utilizadas pelos desenvolvedores através do seguinte código:

javac algum/package/MinhaClasse.java

O javac é o compilador de código do Java que produz arquivos bytecode com a extensão ".class", a partir de arquivo ".java".

Um desenvolvedor que programa há anos em Java talvez nunca tenha utilizado diretamente o javac, isso porque os modernos ambientes integrados de desenvolvimento (IDEs) gerenciam automaticamente a compilação do código para o desenvolvedor. Dessa forma, quando um código é executado dentro da plataforma a própria IDE se encarrega de chamar a ferramenta javac para compilar o código. Outras IDEs compilam o código enquanto o desenvolvedor vai escrevendo-o.

Para a implantação (ou deployment) de projetos normalmente utiliza-se uma ferramenta de build separada como Maven, Ant ou Gradle. Todas essas ferramentas também se utilizam do javac.

Entender a ferramenta de compilação do Java é importante nos casos em que não se tem disponível uma IDE ou não é necessária a instalação de uma para compilação de poucos códigos.

Os parâmetros disponíveis no compilador são:

  • -classpath: Fornece as classes necessárias para compilação;
  • -d some/dir: Informa ao javac onde será a saída dos arquivos compilados;
  • @project.list: Carrega as opções e os códigos-fonte dos arquivos project.list;
  • -help: Exibe opções do javac;
  • -X: Fornece ajuda para opções que não são padrão;
  • -source <version>: Controla a versão do Java que o javac aceitará;
  • -target <version>: Controla a versão dos arquivos ".class";
  • -profile <profile>: Controla o profile que o javac utilizará quando compilar a aplicação;
  • -Xlint: Habilita detalhes sobre o warnings (avisos gerados);
  • -Xstdout: Redireciona a saída da execução da compilação para um arquivo;
  • -g: Adiciona informações de debug ao arquivo ".class".

Uma observação importante é que o javac tem aceitado tradicionalmente os parâmetros -source e -target que controlam a versão do fonte da linguagem que o compilador deveria aceitar, além da versão do formato ".class" gerado. Esta facilidade introduz ao compilador uma complexidade adicional que beneficia apenas alguns desenvolvedores que utilizam essa opção. O Java 8 começou a limitar as funcionalidades desses comandos, visto que o javac no Java 8 aceita apenas as opções source e target de até três versões anteriores, ou seja, apenas as versões JDK 5, 6, 7, e 8.

Ferramenta java

A utilização básica do java é realizada conforme o código a seguir:

java algum.package.MinhaClasse java -jar meu-packaged.jar

Essa ferramenta é responsável por inicializar a Java Virtual Machine (JVM). O ponto de entrada inicial em um programa java é o método main() que existe em uma determinada classe. O método main tem a seguinte assinatura:

public static void main(String[] args) 

Este método é executado em uma thread de uma aplicação que é criada pela JVM, e o seu processo finalizará assim que este método retornar.

Se o usuário invocar um arquivo JAR executável, este deve conter um metadata que informa a JVM qual classe deve ser iniciada. O metadata é o "Main-Class" que está contido no arquivo MANIFEST no diretório META-INF.

Os parâmetros disponíveis no java são:

  • -cp <classpath>: Define o classpah que será lido, ou seja, o parâmetro que indica a JVM onde procurar pacotes e classes;
  • -X, -?, -help: Fornece ajuda sobre a ferramenta java e os seus parâmetros;
  • -D<property=value>: Configura uma propriedade de sistema do Java que pode ser recuperado por um programa;
  • -jar: Executa um JAR executável, ou seja, um pacote e arquivos e pastas;
  • -Xbootclasspath(/a or /p): Executa com um classpath de um sistema alternativo;
  • -client, -server: Seleciona um compilador HotSpot JIT, que otimiza o código em tempo de compilação;
  • -Xint, -Xcomp, -Xmixed: Controla a compilação JIT;
  • -Xms<size>: Configura o heap size mínimo para a JVM;
  • -Xmx<size>: Configura o heap size máximo para a JVM;
  • -agentlib:<agent>, -agentpath:<path to agent>: Especifica um agente JVM Tooling Interface (JVMTI) para ser anexado ao processo sendo inicializado. Os agentes são tipicamente usados para instrumentação e monitorização, inspecionando o estado e controlando a execução de aplicativos em execução na JVM;
  • -verbose: Gera saídas adicionais que são úteis para debugging.

A HotSpot VM contém dois compiladores JIT separados conhecido como compilador cliente e compilador servidor. Eles foram designados para diferentes propostas em que o compilador cliente oferece um desempenho mais previsível e uma inicialização mais rápida, porém, não realiza uma otimização muito eficaz no código, ao contrário do servidor que faz muita otimização, porém é mais lento que o cliente.

Ferramenta jar

A ferramenta jar é utilizada para manipular arquivos Java Archive (.jar). Sua utilização básica é realizada conforme a seguir:

jar cvf meu.jar algumDiretorio/

Os JARs são formatos ZIP que possuem classes Java, recursos adicionais e metadatas. A ferramenta possui cinco modos de operação: Create, Update, Index, List, e Extract.

Esses modos são controlados passando um caractere no comando, mas modificadores opcionais também podem ser utilizados juntos.

Os caracteres utilizados com o comando são:

  • c: Cria um novo arquivo;
  • u: Atualiza um arquivo;
  • i: Indexa um arquivo;
  • t: Lista um arquivo;
  • x: Extrai um arquivo;

Já os modificadores utilizados com o comando são:

  • v: Modo verbose, ou seja, mostra o que está acontecendo;
  • f: Opera em um arquivo nomeado, ao invés da entrada padrão;
  • 0: Armazena, mas não comprime os arquivos adicionados;
  • M: Adiciona conteúdo de um arquivo especificado para o metadata manifest do JAR;
  • e: Torna o JAR executável, com a classe especificada como o ponto de entrada.

A sintaxe do comando jar é muito semelhante ao comando tar, que é amplamente utilizado na plataforma Unix. Isso explica o porquê do comando jar utilizar opções ao invés de parâmetros como os outros comandos.

Sempre que um arquivo .jar é criado, tem-se a criação de um diretório chamado "META-INF", que contém um arquivo chamado "MANIFEST.MF". Por padrão, este possui os cabeçalhos a seguir:

Manifest-Version: 1.0
  Created-By: 1.8.0 (Oracle Corporation) 

Utilizando a opção "m" é possível adicionar metadados a esse arquivo em tempo de criação do JAR.

Frequentemente adiciona-se o par "Main-Class: atributo" que indica o ponto de entrada na aplicação contida no JAR. Isso é tão comum que a opção permite a criação do arquivo MANIFEST e a definição do par "Main-Class: atributo" diretamente.

javadoc

A ferramenta javadoc produz a documentação dos códigos-fonte do Java através da leitura dos comentários contidos no código-fonte. Após essa leitura é realizado um parse destes para um formato de documentação padrão que pode ser extraído para uma variedade de formatos de documento, como HTML e PDF, que são os mais comuns.

A utilização básica do javadoc é realizada conforme a seguir:

javadoc algum.package

Os parâmetros disponíveis nele são:

  • -cp <classpath>: Define o classpath a ser utilizado;
  • -D <directory>: Informa ao javadoc onde deve ser a saída para os documentos gerados;
  • -quiet: Omite a saída, exceto quando for gerado avisos e erros.

jdeps

A ferramenta jdeps é um analisador estático das dependências de pacotes ou classes. Ela pode ser utilizada em diversas situações, tais como: na identificação do código que fez uma determinada chamada interna, quais APIs estão sem documentação, para o rastreamento de dependências transitivas, entre outras.

A utilização básica do jdeps é realizada conforme a seguir:

jdeps br.com.devemedia.MinhaClasse

Os parâmetros disponíveis nele são:

  • -s, -summary: Imprime apenas um resumo das dependências;
  • -v, -verbose: Imprime todas as dependências em nível de classe;
  • -verbose:package: Imprime todas as dependências em nível de pacote, excluindo as dependências dentro do mesmo arquivo;
  • -verbose:class: Imprime todas as dependências em nível de classe, excluindo as dependências dentro do mesmo arquivo;
  • -p <pkg name>, -package <pkg name>: Pesquisa dependências no pacote especificado. Pode-se especificar esta opção múltiplas vezes para pacotes diferentes. As opções -p e -e (apresentada a seguir) são mutualmente exclusivas;
  • -e <regex>, -regex <regex>: Pesquisa dependências nos pacotes que combinam com o padrão de expressão regular especificado;
  • -include <regex>: Restringe a análise para classes que combinam com o padrão. Esta opção filtra a lista de classes a ser analisada. Nesse caso, pode-se utilizar -p e -e em conjunto;
  • -jdkinternals: Pesquisa dependências a nível de classe nas APIs internas da JDK;
  • -apionly: Restringe a análise apenas para as APIs;
  • -R, -recursive: Recursivamente percorre todas as dependências;
  • -h, -?, -help: Imprime a mensagem de ajuda para o jdeps.

jps

A ferramenta jps fornece uma lista de todos os processos da JVM que estão ativos na máquina local (ou em uma máquina remota, caso uma instância de jstatd esteja executando em um lado remoto).

A sua utilização básica é realizada conforme a seguir:

jps <URL remota>

Os parâmetros disponíveis no jps são:

  • -m: Tem como saída os argumentos passados para o método main;
  • -l: Tem como saída o nome completo do pacote para a classe principal da aplicação;
  • -v: Tem como saída os argumentos passados para a JVM.

jstat

A ferramenta jstat exibe algumas estatísticas básicas sobre o processo Java fornecido, que normalmente é local, mas pode estar localizado em uma máquina remota.

A utilização básica do jstat é realizada conforme a seguir:

jstat <pid>

Os parâmetros disponíveis são:

  • -options: Informa uma lista de tipos de relatórios que o jstat pode produzir;
  • -class: Informa a atividade do classloading por data;
  • -compiler: Mostra o processo de compilação do JIT até o momento;
  • -gcutil: Informa detalhes de como está o GC;
  • -printcompilation: Fornece mais detalhes da compilação.

Uma sintaxe comum que o jstat utiliza para identificar um processo é dado conforme a seguir:

 [<protocol>://]<vmid>[@hostname][:port][/servername] 

Essa sintaxe também pode ser utilizada para identificar um processo remoto que é frequentemente conectada via JMX, que é uma API de gerenciamento de recursos, tais como aplicações, serviços e JVM. No entanto, é mais comum ser utilizado localmente apenas utilizando o VM ID, que é o id do processo do sistema operacional.

jstatd

O jstatd oferece uma forma de gerar informações sobre as JVMs locais disponíveis na rede. Ele opera através do RMI, que é a interface que permite a execução de chamadas remotas, ou JMX.

O jstatd necessita de configurações especiais de segurança que pode diferir dependendo do padrão das JVM.

A utilização básica do jstatd é realizada conforme a seguir:

jstatd <options>

Para inicia-lo primeiramente é preciso criar o um arquivo e nomeá-lo como jstatd.policy. A seguir temos como este arquivo pode ser criado:

grant codebase "file:${java.home}../lib/tools.jar {
           permission java.security.AllPermission
  }

Este concede todas as permissões de segurança para qualquer classe carregada a partir do arquivo tools.jar do JDK.

Para carregar o jstatd com esta política basta utilizar a linha de comando a seguir:

jstatd -J-Djava.security.policy=<caminho do jstat.policy>

O parâmetro disponível no jstatd é o -p <port>, que pesquisa por um registro RMI existente na porta e cria um registro se não for encontrado.

jinfo

Esta ferramenta exibe as propriedades do sistema e opções da JVM para a execução de processos Java.

A sua utilização básica é realizada conforme a seguir:

jinfo <ID do processo> jinfo <Arquivo principal>

Os parâmetros disponíveis são:

  • -flags, que exibe todas as flags da JVM;
  • -sysprops, que exibe todas as propriedades do sistema.

Esse comando não é muito utilizado pelos desenvolvedores, mas pode ser útil em certas ocasiões para verificar as propriedades de um sistema.

jstack

A ferramenta jstack produz um stack trace para cada thread de um processo Java, ou seja, uma mensagem mostrando o seu estado atual na JVM.

A utilização básica do jstack é realizada conforme a seguir:

jstack <process ID>

Os parâmetros disponíveis são:

  • -F: Força o descarregamento de uma thread;
  • -l: Contém informações adicionais sobre os bloqueios (locks).

É importante salientar que a geração do stack trace não pausa ou termina um processo Java.

Outra dica importante é que o arquivo produzido pelo jstack pode ser muito grande, assim será necessário realizar um pós-processamento deste arquivo.

jmap

A ferramenta jmap fornece uma view da alocação de memória para um processo Java que está executando.

A sua utilização básica é realizada da seguinte forma:

jmap <processo>

Os seus parâmetros disponíveis são:

  • -histo: Produz um histograma do estado atual da memória alocada;
  • -histo:live: Esta versão do histograma apenas exibe informações de objetos que estão ativos;
  • -heap: Produz um descarregamento do heap para os processos em execução.

javap

A ferramenta javap é um disassembler para os arquivos “.class” do Java. Ela basicamente realiza pesquisas dentro dos arquivos “.class”.

O javap pode exibir o bytecode em que os métodos do Java foram compilados, assim como informações referentes ao pool.

Por padrão, o javap exibe assinaturas dos métodos public, protected e default. Porém, também pode ser utilizado um parâmetro para mostrar os métodos private.

A sua utilização básica é realizada com o seguinte comando:

javap <nome da classe>

Os parâmetros disponíveis são:

  • -c: Descompila o bytecode;
  • -v: Modo verbose que inclui informações do pool;
  • -p: Opção para incluir também os métodos privados nas assinaturas exibidas.

VisualVM

O JVisualVM, também chamado de VisualVM, é uma ferramenta gráfica baseada na plataforma NetBeans, utilizada para monitorar JVMs.

As ferramentas de linha de comando discutidas anteriormente são essencialmente agregadas graficamente no VisualVM.

A ferramenta foi introduzida com a versão Java 6 e está contida no pacote de distribuição da linguagem. Para fazer o download da versão mais recente do VisualVM basta acessar o site disponível na seção Links.

Se for realizado o download de uma versão mais recente o binário “visualvm” deve ser adicionado ao PATH, caso contrário será carregado o binário padrão da JRE, que é o ambiente de execução Java.

Para abrir o VisualVM basta ir até a pasta bin da JDK e abri-lo normalmente, ou também pode ser utilizado um duplo clique em cima do nome do arquivo na pasta C:\Program Files (x86)\Java\jdk1.8.0_45\bin>jvisualvm.exe.

Após isso o VisualVM será carregado conforme mostra a Figura 1.

VisualVM sendo carregado no Sistema

Figura 1. VisualVM sendo carregado no Sistema.

Na primeira vez que ele for carregado, serão realizados alguns ajustes na máquina. Após isso, o VisualVM abrirá a tela da Figura 2.

Tela
principal do VisualVM

Figura 2. Tela principal do VisualVM.

Para exibir as tabs do VisualVM basta dar um duplo clique em “VisualVM” no canto esquerdo da janela. Com isso serão exibidas as abas Overview, Monitor, Threads e Sampler, como mostra a Figura 3.

Tela do
VisualVM exibindo as abas disponíveis

Figura 3. Tela do VisualVM exibindo as abas disponíveis.

A aba chamada Overview, exibida na Figura 4, fornece um resumo das informações sobre os processos Java, dentre as quais estão flags e propriedades do sistema, além da versão do Java sendo executado.

Tela Da
aba Overview sendo exibida

Figura 4. Tela Da aba Overview sendo exibida.

A aba chamada Monitor, mostrada na Figura 5, exibe gráficos e dados sobre as partes ativas da JVM, dentre os quais estão o uso de CPU para o Garbage Collection (GC), número de classes carregadas e descarregadas, informações sobre a memória heap, número de thread executando, entre outras.

Tela da
aba Monitor sendo exibida

Figura 5. Tela da aba Monitor sendo exibida.

Já a aba chamada Threads, da Figura 6, exibe informações sobre as threads que estão executando na JVM. As informações são exibidas como uma linha do tempo contínua que torna possível inspecionar detalhes de cada uma em particular.

Nesta aba tem-se uma view similar ao jstack, mas a view disponível pela VisualVM é muito melhor, podendo diagnosticar deadlocks e starvation (inanição, ou seja, quando um processo nunca é executado).

Tela da
aba Threads sendo exibida

Figura 6. Tela da aba Threads sendo exibida.

A aba chamada Sampler da Figura 7 exibe informações da memória ou da CPU. Nesta tela é possível verificar os objetos mais comuns que estão sendo referenciados.

Tela da
aba Sampler sendo exibida

Figura 7. Tela da aba Sampler sendo exibida.

O VisualVM também permite que mais funcionalidades sejam incorporadas à ferramenta através da instalação de plug-ins. Para verificar quais estão disponíveis basta ir em “Tools > Plugins” no menu superior do VisualVM.

Um plug-in bastante útil é o Mbeans, pois ele permite ao operador interagir com os Java management servies (ou MBeans). Isso é possível através do JMX que permite um controle em tempo de execução das aplicações Java.

Após a instalação do plug-in tem-se a aba Mbeans disponível no VisualVM, como mostra a Figura 8.

Tela da
aba MBeans sendo exibida

Figura 8. Tela da aba MBeans sendo exibida.

Outro plug-in importante é o VisualGC, sendo considerada uma das melhores ferramentas para debugging disponíveis. Além disso é um excelente meio de entender o funcionamento do GC, como mostra a Figura 9.

Tela da
aba VisualGC sendo exibida

Figura 9. Tela da aba VisualGC sendo exibida.

As ferramentas disponibilizadas na plataforma do Java ajudam a resolver uma série de problemas comuns do dia a dia. Entende-las também ajuda a melhorar o software desenvolvido, além de facilitar na hora de encontrar problemas como deadlocks e starvation.

Normalmente alguns usuários preferem as ferramentas gráficas enquanto outros se sentem mais familiarizados com as ferramentas de linha de comando. Ambos os ambiente são disponibilizados na plataforma Java. E o VisualVM oferece uma forma gráfica de verificar os dados que são obtidos com as ferramentas de linha de comando, sendo também uma opção bastante poderosa e com múltiplas funcionalidades.

Espero que tenham gostado e até a próxima.

Bibliografia

[1] Java SE Core Technologies - Java Compiler
http://www.oracle.com/technetwork/articles/javase/javac-137034.html

[2] Java Platform Standard Edition 8 Documentation
https://docs.oracle.com/javase/8/docs/

[3] Richard Hightower. Professional Java Tools For Extreme Programming. Editora John Wiley Consumer, 2004.

[4] Ferramenta VisualVM
http://visualvm.java.net/