Como ler um thread dump da JVM

Cole a saída do jstack ou do jcmd Thread.print, ou abra um arquivo .txt ou .log, e pressione Analisar localmente. O dump é lido neste navegador: o resumo conta as threads por java.lang.Thread.State, o cartão de baixo classifica os frames de pilha que se repetem e os achados nomeiam as threads que esperam um lock mantido por outra.

Um dump de 13 threads e 4,3 KB voltou como RUNNABLE 4, WAITING 3, BLOCKED 2, TIMED_WAITING 2 e UNKNOWN 2, com java.base/java.lang.Thread.sleep(Native Method) como frame mais repetido (3 threads) e duas threads HTTP esperando o monitor que a cache-writer mantinha. Nada é enviado e nenhuma cópia do dump é guardada.

  1. Cole o dump na caixa ou solte um arquivo .txt ou .log nela. Servem a saída do jstack, do jstack -l e do jcmd <pid> Thread.print; o nome do arquivo fica ao lado da caixa e some assim que você cola outro texto.
  2. Pressione Analisar localmente. O resumo mostra uma linha por nome de estado, o cartão abaixo lista os doze frames mais frequentes com suas contagens, e os dois são preenchidos na mesma passada.
  3. Leia a lista de achados: um deadlock de Java é informado uma vez e depois separado nas threads que esperam umas pelas outras, e um lock que uma thread espera enquanto outra o mantém aparece com os dois lados.
  4. Use Copiar para levar o resultado, ou pressione Baixar para obter um relatório em texto simples com o nome do arquivo carregado (thread-dump-analysis.txt quando você cola o dump). O relatório traz as contagens, a tabela de estados, os principais frames e os achados, e não o dump colado.
  5. Limpar esvazia a caixa, as tabelas e os achados e devolve o texto de espaço reservado; depois disso a página não guarda nada.

O que as tabelas e os achados significam

O que o analisador lê

Só texto é analisado, e só nas formas que um dump da JVM escreve: cabeçalhos de thread (nome entre aspas seguido de prio=, tid= ou nid=), linhas java.lang.Thread.State, frames at e as linhas waiting to lock / locked / parking to wait for que o jstack -l acrescenta. Threads da VM são impressas sem linha de estado, então caem na linha UNKNOWN — duas das treze do exemplo acima.

O relatório de deadlock que o jstack anexa depois da lista de threads é lido como relatório, não como novas threads: um dump com três threads e um deadlock continua com três threads, e o relatório vira um achado mais uma linha por par em espera.

Como os números são contados

Todo frame de toda thread conta, não apenas os três mais internos, porque um frame compartilhado mais fundo na pilha é exatamente a marca de um caminho de chamada repetido. Em um exemplo de 24 threads cujo quinto frame é java.base/java.lang.reflect.Method.invoke(Method.java:568), esse frame aparece 18 vezes no dump e na tabela.

Uma correlação de lock precisa das duas metades no mesmo dump: a linha waiting to lock <id> de uma thread e a linha locked <id> de outra. Locks cujo dono não está no arquivo — dump truncado ou jstack sem -l — continuam contados como espera, mas nada é afirmado sobre quem os mantém.

O tamanho não é limite prático: um dump de 240 threads e 92 KB voltou com 240 threads, 6 delas bloqueadas em um único monitor e três frames contados 240 vezes cada, porque o trabalho acontece nesta máquina.

Limites e compatibilidade

Um log de falha do HotSpot (hs_err_pid*.log) lista threads Java mas não traz nenhuma linha java.lang.Thread.State, então a página diz isso em vez de desenhar tabelas vazias. Qualquer outro texto sem um único cabeçalho de thread recebe a mesma resposta, e uma caixa vazia recebe um aviso em vez de um resultado.

Lê-se um dump por vez. O analisador não se conecta a uma JVM, não amostra um processo em execução nem observa mudanças em um arquivo; para uma visão ao vivo, o Flight Recorder ou um profiler são a ferramenta certa.

Nomes de estado, assinaturas de frame e identificadores de lock são impressos exatamente como o dump os escreve, em inglês, porque são dados; os rótulos ao redor seguem o idioma da página.

Ferramentas recentes: