Skip to content

{ Monthly Archives } May 2008

Thread Dumps


A obtenção de um thread dump ajuda a determinar o que um servidor está fazendo em um dado momento. Um thread dump lista todas as threads sendo executadas por uma aplicação Java e apresenta um stack trace para cada thread. Examinar um thread dump pode dar pistas de se um servidor está parando em determinados momentos. Por exemplo, assumindo que um servidor parou por algum motivo após uma aplicação ter sido iniciada, um thread dump pode ajudar a localizar a causa da parada.



A JVM produz um thread dump quando recebe um sinal QUIT. Este sinal pode ser enviado de várias formas, mas ele é geralmente enviado por um comando que envia sinais ou por uma combinação de teclas executadas na janela da aplicação Java em execução. No Unix/Linux, a combinação <ctrl>\ ou o comando kill -QUIT id-do-processo (equivale ao kill -3 id-do-processo) podem gerar um thread dump. No Windows, utilize a combinação <ctrl><break>. Outra forma, é utilizar a interface GUI do jconsole que vem com o JDK 5.



O jconsole contém seis abas que mostram diversas informações sobre uma aplicação em execução. Uma delas é nomeada Threads e provê as mesmas informações mostradas por um thread dump.



Para executar uma aplicação Java de forma que esta possa ser monitorada pelo jconsole é necessário iniciá-la com o argumento -Dcom.sun.management.jmxremote. No caso do JBoss AS por exemplo, este argumento pode ser informado na variável de ambiente JBOSS_OPTS ou nos scripts de inicialização (run.*).



O jconsole também pode ser utilizado para substituir as funções de gerenciamento oferecidas pelo jmx-console. Você pode ler mais a respeito e ver como realizar a configuração do JBoss para suportar o gerenciamento de seus MBeans pelo jconsole, lendo esta página no wiki do JBoss.



A listagem produzida por um thread dump é longa. Desta forma, para visualizá-la é interessante iniciar o JBoss AS com o comando abaixo que irá gerar toda a saída do console padrão e de erros para o arquivo jboss.log:



$ run.sh >> jboss.log 2>&1


Monitore o arquivo jboss.log com o comando tail em um outro teminal e após perceber que o JBoss finalizou seu startup, execute a combinação de teclas <ctrl>\ na janela de execução do JBoss. Isto irá gerar um thread dump e também irá desvincular o JBoss AS do seu terminal corrente (sem entretanto, pará-lo).



Você poderá observar então o conteúdo do arquivo jboss.log que irá conter o thread dump. Ele irá conter uma lista de todas as threads que estão alocadas. Cada thread tem um nome e na maioria das vezes, este nome dá boas dicas da sua função. Você pode por exemplo adivinhar as funções das threads nomeadas “RMI TCP Accept-4444″ e “ScannerThread” não é? As threads listadas no início do thread dump são as que são utilizadas pelo JBoss e geralmente, as que estão no final são das da JVM. Segue uma lista de threads interessantes em execução no JBoss:

















Nome da Thread Descrição
CompilerThread1 Utilizada para a compilação de código Java, geralmente JSPs. Pode haver tantas quanto forem os processadores da máquina. Elas não estão presentes se não estiver sendo executada alguma compilação
GC Daemon Utilizada para a execução do Garbage Collector. Esta thread está presente enquanto ele está sendo executado.
http-0.0.0.0-8080-1 Utilizada para processar requisições HTTP de algum cliente. O endereço IP (0.0.0.0) e a porta são variáveis de acordo com a conexão socket aberta. O dígito final varia por requisição



O stack trace abaixo da descrição da thread mostra a pilha de execução dos métodos executados pela thread no momento em que o thread dump foi gerado e é extremamente útil para se descobrir o que estava ocorredo naquele momento. Observando com calma, percebemos o que a thread estava fazendo:



Name: http-0.0.0.0-8080
State: RUNNABLE
Total blocked: 0 Total waited: 0

Stack trace:
java.net.PlainSocketImpl.socketAccept(Native Method)
java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
java.net.ServerSocket.implAccept(ServerSocket.java:450)
java.net.ServerSocket.accept(ServerSocket.java:421)
org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:60)
org.apache.tomcat.util.net.PoolTcpEndpoint.acceptSocket(PoolTcpEndpoint.java:407)
org.apache.tomcat.util.net.PoolTcpEndpoint.run(PoolTcpEndpoint.java:647)
java.lang.Thread.run(Thread.java:595)


Outra forma de se gerar um thread dump é através do jmx-console do JBoss ou do utilitário de linha de comando twiddle. Para obter um thread dump através do utilitário twiddle em um servidor linux, o seguinte comando poderia ser executado:



$ twiddle.sh invoke jboss.system:type=ServerInfo listThreadDump



Para buscar mais informações a respeito deste assunto, sugiro que você leia:


Implantando aplicações no JBoss via suporte a WebDAV


O Servidor JBoss AS suporta a implantação de diversos arquivos necessários para a execução de uma aplicação Java (*.[jewsr]ar *-ds.xml …) até mesmo se eles estiverem disponíveis em uma URL como, por exemplo, http://servidor/diretorio-com-suporte-a-WebDAV/. Este mecanismo é útil em diversas situações. Neste post, vou ilustrar um caso prático: suponhamos que você deseje instalar uma única instância do CruiseControl como a ferramenta responsável pelo processo de Integração Contínua de diversas aplicações que precisam ser implantadas em diferentes instâncias de JBoss, sendo executadas em várias máquinas distintas.



Uma possível solução para este problema é:



  • Configurar um servidor Apache na mesma máquina que roda o CruiseControl, ativando os módulos responsáveis pelo suporte ao WebDAV ou, de maneira alternativa, instalando um Servlet que ofereça este suporte ao container que executa o CruiseControl;
  • Configurar no Apache uma URL como, por exemplo, http://cruisecontrol.minhaempresa.com/aplicacaoX/ apontando para o diretório no qual serão gerados os arquivos da aplicação X que precisam ser implantados em uma instância de JBoss;
  • Configurar a URL anterior no JBoss para que o mesmo possa fazer uma busca (scan) (via comando PROPFIND do WebDAV) pelos arquivos da aplicação X, que estão disponíveis na URL;

  • Desabilitar o scan automático do JBoss, para que ele não perca o seu tempo tentando verificar se novas versões dos arquivos precisam ser implantadas ou não (ele será avisado sobre isto, pelo CruiseControl);
  • Fazer o script de controle do CruiseControl para o aplicação X enviar o comando scan para o JBoss, quando for finalizado o processo de geração (build) dos arquivos desta aplicação, a fim de que este servidor possa realizar a implantação destes arquivos;
  • Fazer o processo de testes da aplicação X (via JUnit ou TestNG por exemplo) ser iniciado apenas quando o processo de implantação no servidor terminar. Em alguns casos, principalmente na situação em que a implantação é responsável por gerar várias tabelas em um SGBD (como quando se utiliza a feature schemaexport do Hibernate), este processo pode ser um pouco lento, gerando então um pequeno atraso no início dos testes, que só deverão ser iniciados após a completa verificação de que a implantação foi finalizada e bem sucedida.


Uma observação sob esta solução é que, as máquinas que rodam as instâncias de JBoss que serão responsáveis pelas implantações das aplicações X, Y, …, não precisarão ter serviços como SSH remoto, FTP, NFS, ou quaisquer outros que possibilitem a cópia remota dos arquivos a serem implantados. Esta característica pode ser vista com bons olhos por analistas de segurança já que ela praticamente elimina a necessidade de acesso remoto ao servidor para fins de cópias de arquivo.



Ficaria muito extenso este post, se eu fosse entrar em detalhes sobre como realizar a configuração do CruiseControl, do Apache e de seu suporte ao WebDAV. Desta forma, vou apenas apenas dar algumas dicas de como proceder a configuração do JBoss para a realização de algumas tarefas:



  • Para desabilitar o scan automático do JBoss é necessário ajustar o valor do atributo ScanEnabled do MBean jboss.deployment:flavor=URL,type=DeploymentScanner para false. Isto é realizado no arquivo jboss-service.xml da configuração que será executada pelo JBoss;

  • Para incluir a URL que será acessada pelo JBoss a fim de que o mesmo possa verificar que arquivos estão em um diretório-com-suporte-a-WebDAV/ é necessário adicionar ao atributo URLs do mesmo MBean a URL a ser utilizada para o scan no servidor HTTP (note a barra final no fim da URL pois ela é ESSENCIAL). Exemplo:

    <attribute name=”URLs”>
    deploy/,http://servidor/diretorio-com-suporte-a-WebDAV/
    </attribute>

  • Para enviar o comando scan para o JBoss, ao final do processo de build da aplicação X, será necessário a execução de da operação operação scan do mesmo MBean. Isto pode ser feito de diversas formas, sendo que, uma delas é, através da inclusão das seguintes tasks em um script Ant (disponíveis em jars do diretório client do JBoss):


    <jmx>
    <invoke target=”jboss.deployment:flavor=URL,type=DeploymentScanner” operation=”scan”/>
    </jmx>

  • Para instanciar o JBoss (na versão 4.0.5) com o suporte ao scan de URLs com o suporte a WebDAV é preciso executar o run.{sh,bat} passando os parâmetros do exemplo abaixo (ATENÇÃO: se você esquecê-los tomará um TOCO ;-) do JBoss). E mais um pouco de atenção ainda: a informação abaixo é MUIIITOO difícil de ser encontrada em algum manual do JBoss. Fábio Sbano, um amigo Linuxer e Geek de trabalho na Andima, também colaborador do Lado Servidor, encontrou este detalhe no JIRA do JBoss para que pudesse fechar a solução abaixo. Desta forma, acho que seria legal a Red Hat rever a documentação e acertar com um pouco mais de ênfase pequenos detalhes como este nesta página ou nesta.


    $ run.sh -L commons-logging.jar -L commons-httpclient.jar -L webdavlib.jar

  • Caso você esteja utilizando a versão 4.2.2 do JBoss, para que o suporte ao WebDAV funcione, também é necessário que a biblioteca webdavlib.jar esteja disponível no diretório $JBOSS_HOME/lib (por algum motivo ela desapareceu nesta versão) e a linha de execução do run também deverá conter o parâmetro -L commmons-codec.jar, caso contrário, você também irá ter problemas.


É isto… em próximos posts, mais dicas!

Vídeo sobre as novas características do Glassfish v3

Treinamento de JBoss na Cabal

No sábado passado iniciei um treinamento de JBoss para o Cliente Cabal Brasil, em Brasília.
A Cabal foi minha Cliente em treinamentos que ministrei em parceria com a Argo Navis enquanto eu ainda possuia uma infra-estrutura para cursos abertos, no Terraço Shopping, em Brasília.
Agora, é com grande satisfação que posso atendê-los novamente, oferencendo os seguintes treinamentos:

  1. Introdução a Java EE utilizando o JBoss AS, de 10 a 17 de maio;
  2. Administração básica do JBoss AS, de 17 de maio a 7 de junho;
  3. Arquitetura e funcionamento do JBoss AS, de 26 de julho a 23 de agosto;

Este curso, fechado para a Cabal, ocorre aos sábados, das 10:00 às 17:00.

Tolerância Zero - Top 10

Este post é só pra descontrair… Lembranças do amigo Sérgio Murilo (da Andima), que está de férias neste momento e adora responder a alguém que diz “bom dia” a ele na segunda feira: “Bom dia?? Por quê?”
1. Quando te vêem deitado, de olhos fechados, na sua cama, com a luz
apagada e te perguntam:
- Você [...]

De BlueHost p/ DreamHost…

Acabo de fazer uma mudança do servidor de hospedagem e, por isto, o conteúdo deste site está em processo de migração. Em breve, estará tudo normalizado…