Quando precisamos diagnosticar problemas de performance, deadlocks ou travamentos em aplicações Java, uma das ferramentas mais valiosas disponíveis é o thread dump.
Tradicionalmente, gerar um thread dump exigia o uso de ferramentas externas como jstack, jcmd ou até mesmo acesso direto ao processo da JVM. Com as versões mais recentes do JDK, isso mudou: agora é possível gerar thread dumps programaticamente por meio da interface HotSpotDiagnosticMXBean.
Neste artigo, vamos explorar a nova API dumpThreads(), entender seus casos de uso e aprender como utilizá-la em aplicações reais.
O que é um Thread Dump?
Um thread dump é uma fotografia do estado de todas as threads de uma JVM em um determinado momento.
Ele normalmente contém informações como:
- Nome e ID das threads
- Estado atual (
RUNNABLE,WAITING,BLOCKED, etc.) - Stack trace de cada thread
- Informações sobre locks e sincronização
- Possíveis deadlocks
- Informações sobre Virtual Threads (quando aplicável)
Essa informação é extremamente útil para investigar:
- Aplicações travadas
- Deadlocks
- Alto consumo de CPU
- Lentidão em requisições
- Contenção de recursos
- Thread starvation
A Nova API dumpThreads()
A interface HotSpotDiagnosticMXBean ganhou um novo método chamado dumpThreads().
Sua assinatura é semelhante a:
public void dumpThreads(
String outputFile,
ThreadDumpFormat format
) throws IOException;
O método recebe:
- O caminho absoluto do arquivo de saída
- O formato desejado para o dump
Os formatos disponíveis são:
HotSpotDiagnosticMXBean.ThreadDumpFormat.TEXT_PLAIN
HotSpotDiagnosticMXBean.ThreadDumpFormat.JSON
Isso permite gerar dumps tanto para análise manual quanto para processamento automatizado.
Criando um Utilitário para Gerar Thread Dumps
Vamos criar um método simples para gerar um dump em formato JSON.
import com.sun.management.HotSpotDiagnosticMXBean;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
public class ThreadDumpUtil {
public static void takeThreadDump(String outputFile) {
var hotSpotDiagnosticMXBean =
ManagementFactory.getPlatformMXBean(
HotSpotDiagnosticMXBean.class);
try {
if (!new File(outputFile).isAbsolute()) {
throw new IllegalArgumentException(
"O caminho do arquivo deve ser absoluto.");
}
hotSpotDiagnosticMXBean.dumpThreads(
outputFile,
HotSpotDiagnosticMXBean.ThreadDumpFormat.JSON);
} catch (IOException e) {
throw new RuntimeException(
"Erro ao gerar thread dump",
e);
}
}
}
A utilização é bastante simples:
ThreadDumpUtil.takeThreadDump(
"/tmp/thread-dump.json");
Após a execução, o arquivo será criado no caminho informado.
Atenção ao Caminho do Arquivo
Um detalhe importante é que o método exige um caminho absoluto.
Exemplo válido:
"/tmp/thread-dump.json"
Exemplo inválido:
"thread-dump.json"
Caso um caminho relativo seja informado, uma exceção será lançada.
Por isso, é uma boa prática validar o caminho antes de chamar a API.
TEXT_PLAIN vs JSON
Uma das novidades mais interessantes é o suporte nativo ao formato JSON.
Formato Texto
hotSpotDiagnosticMXBean.dumpThreads(
"/tmp/threads.txt",
HotSpotDiagnosticMXBean.ThreadDumpFormat.TEXT_PLAIN);
O resultado será semelhante ao que vemos ao executar um jstack:
"main" #1
java.lang.Thread.State: RUNNABLE
...
Esse formato é ideal para análise humana.
Formato JSON
hotSpotDiagnosticMXBean.dumpThreads(
"/tmp/threads.json",
HotSpotDiagnosticMXBean.ThreadDumpFormat.JSON);
O resultado passa a ser estruturado:
{
"threadName": "main",
"threadId": 1,
"threadState": "RUNNABLE"
}
Esse formato é excelente para:
- Ferramentas de observabilidade
- Dashboards
- Sistemas de monitoramento
- Processamento automatizado
- Integração com pipelines de diagnóstico
Casos de Uso em Produção
Gerar Dumps Quando Houver Muitas Falhas
Imagine uma aplicação começando a apresentar timeouts em massa.
Podemos capturar automaticamente um dump para análise posterior:
if (timeoutCount > 100) {
ThreadDumpUtil.takeThreadDump(
"/var/log/dumps/timeouts.json");
}
Isso ajuda a entender exatamente o que estava acontecendo na JVM durante o incidente.
Expor um Endpoint Administrativo
Outra estratégia comum é disponibilizar um endpoint interno para gerar dumps sob demanda.
@PostMapping("/admin/thread-dump")
public void threadDump() {
ThreadDumpUtil.takeThreadDump(
"/tmp/admin-dump.json");
}
Essa abordagem é bastante útil em ambientes Kubernetes ou plataformas onde não existe acesso direto ao sistema operacional.
Capturar Informações Antes do Encerramento
Também é possível registrar um shutdown hook para gerar um dump antes da aplicação ser finalizada.
Runtime.getRuntime().addShutdownHook(
new Thread(() ->
ThreadDumpUtil.takeThreadDump(
"/logs/shutdown.json")
)
);
Isso pode ser útil para investigar encerramentos inesperados.
Diagnóstico Remoto via JMX
Como a funcionalidade é exposta por meio de um MXBean, ferramentas de monitoramento podem acioná-la remotamente utilizando JMX.
Isso elimina a necessidade de acessar diretamente o servidor para coletar informações da JVM.
Em ambientes corporativos, essa capacidade pode simplificar bastante o processo de troubleshooting.
Comparando com jstack
| Recurso | jstack | dumpThreads() | | ---------------------------------- | -------- | ------------- | | Requer acesso ao processo | Sim | Não | | Pode ser automatizado | Limitado | Sim | | Disponível via JMX | Não | Sim | | Suporte a JSON | Não | Sim | | Pode ser usado dentro da aplicação | Não | Sim |
Ferramentas como jstack e jcmd continuam sendo excelentes para análises manuais.
Por outro lado, a nova API é muito mais interessante quando o objetivo é automatizar diagnósticos e integrar informações da JVM a plataformas de observabilidade.
Conclusão
A nova API dumpThreads() representa uma evolução importante para diagnósticos em aplicações Java.
Entre seus principais benefícios estão:
- Geração programática de thread dumps
- Integração nativa com JMX
- Suporte a formato JSON
- Facilidade de automação
- Melhor integração com ambientes em nuvem e containers
Se você trabalha com observabilidade, monitoramento ou construção de ferramentas operacionais para JVMs, vale a pena explorar essa funcionalidade.
Ela permite transformar uma tarefa tradicionalmente manual em algo totalmente automatizado e integrado ao ciclo de operação da aplicação.
