Despejo de Threads Java – VisualVM, jstack, kill -3, jcmd

Despejo de Threads em Java é uma lista de todas as threads ativas na Máquina Virtual Java.

Despejo de Threads em Java

Despejo de threads em Java é muito útil para analisar gargalos na aplicação e situações de deadlock. Aqui aprenderemos várias maneiras de gerar um despejo de threads para um programa Java. Estas instruções são válidas para sistemas operacionais *nix, mas no Windows os passos podem ser um pouco diferentes.

  1. Profiler VisualVM: Se você está analisando a aplicação para lentidão, deve usar um profiler. Podemos gerar despejo de threads para qualquer processo usando o profiler VisualVM muito facilmente. Basta clicar com o botão direito no processo em execução e selecionar a opção “Thread Dump” para gerá-lo.
  2. jstack: O Java vem com a ferramenta jstack através da qual podemos gerar um despejo de threads para um processo Java. Este é um processo de duas etapas.
    1. Descubra o PID do processo Java usando o comando ps -eaf | grep java
    2. Execute a ferramenta jstack como jstack PID para gerar a saída do despejo de threads no console. Você pode anexar a saída do despejo de threads a um arquivo usando o comando “jstack PID >> mydumps.tdump
  3. Podemos usar o comando kill -3 PID para gerar o despejo de threads. Isso é um pouco diferente de outras maneiras de gerar o despejo de threads. Quando o comando kill é emitido, o despejo de threads é gerado no System out do programa. Portanto, se for um programa Java com o console como System out, o despejo de threads será impresso no console. Se o programa Java for um servidor Tomcat com o System out como catalina.out, então o despejo de threads será gerado no arquivo.
  4. O Java 8 introduziu a utilidade jcmd. Você deve usar isso em vez do jstack se estiver usando o Java 8 ou superior. O comando para gerar o despejo de threads usando jcmd é jcmd PID Thread.print.

Acima estão quatro maneiras diferentes de gerar despejo de threads em Java. Geralmente, prefiro os comandos jstack ou jcmd para gerar e analisar despejos de threads. Note que, de qualquer maneira escolhida, o despejo de threads será sempre o mesmo.

Exemplo de Despejo de Threads em Java

Em meu último post, expliquei sobre java Timer, aqui está um despejo de threads gerado para o mesmo programa.

2012-12-26 22:28:39
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode):

"Attach Listener" daemon prio=5 tid=0x00007fb7d8000000 nid=0x4207 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Timer-0" daemon prio=5 tid=0x00007fb7d4867000 nid=0x5503 waiting on condition [0x00000001604d9000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.journaldev.threads.MyTimerTask.completeTask(MyTimerTask.java:19)
	at com.journaldev.threads.MyTimerTask.run(MyTimerTask.java:12)
	at java.util.TimerThread.mainLoop(Timer.java:555)
	at java.util.TimerThread.run(Timer.java:505)

"Service Thread" daemon prio=5 tid=0x00007fb7d482c000 nid=0x5303 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=5 tid=0x00007fb7d482b800 nid=0x5203 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=5 tid=0x00007fb7d4829800 nid=0x5103 waiting on condition [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=5 tid=0x00007fb7d4828800 nid=0x5003 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=5 tid=0x00007fb7d4812000 nid=0x3f03 in Object.wait() [0x000000015fd26000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x0000000140a25798> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
	- locked <0x0000000140a25798> (a java.lang.ref.ReferenceQueue$Lock)
	at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
	at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:177)

"Reference Handler" daemon prio=5 tid=0x00007fb7d4811800 nid=0x3e03 in Object.wait() [0x000000015fc23000]
   java.lang.Thread.State: WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0x0000000140a25320> (a java.lang.ref.Reference$Lock)
	at java.lang.Object.wait(Object.java:503)
	at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
	- locked <0x0000000140a25320> (a java.lang.ref.Reference$Lock)

"main" prio=5 tid=0x00007fb7d5000800 nid=0x1703 waiting on condition [0x0000000106116000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
	at java.lang.Thread.sleep(Native Method)
	at com.journaldev.threads.MyTimerTask.main(MyTimerTask.java:33)

"VM Thread" prio=5 tid=0x00007fb7d480f000 nid=0x3d03 runnable 

"GC task thread#0 (ParallelGC)" prio=5 tid=0x00007fb7d500d800 nid=0x3503 runnable 

"GC task thread#1 (ParallelGC)" prio=5 tid=0x00007fb7d500e000 nid=0x3603 runnable 

"GC task thread#2 (ParallelGC)" prio=5 tid=0x00007fb7d5800000 nid=0x3703 runnable 

"GC task thread#3 (ParallelGC)" prio=5 tid=0x00007fb7d5801000 nid=0x3803 runnable 

"GC task thread#4 (ParallelGC)" prio=5 tid=0x00007fb7d5801800 nid=0x3903 runnable 

"GC task thread#5 (ParallelGC)" prio=5 tid=0x00007fb7d5802000 nid=0x3a03 runnable 

"GC task thread#6 (ParallelGC)" prio=5 tid=0x00007fb7d5802800 nid=0x3b03 runnable 

"GC task thread#7 (ParallelGC)" prio=5 tid=0x00007fb7d5803800 nid=0x3c03 runnable 

"VM Periodic Task Thread" prio=5 tid=0x00007fb7d481e800 nid=0x5403 waiting on condition 

JNI global references: 116

O thread dump é a lista de todos os threads, cada entrada mostra informações sobre o thread que inclui o seguinte na ordem de aparência.

  1. Nome do Thread: Nome do Thread
  2. Prioridade do Thread: Prioridade do thread
  3. ID do Thread: Representa o ID único do Thread
  4. Status do Thread: Fornece o estado atual do thread, por exemplo, EXECUTÁVEL, AGUARDANDO, BLOQUEADO. Ao analisar um deadlock, procure pelos threads bloqueados e pelos recursos nos quais eles estão tentando adquirir bloqueio.
  5. Pilha de chamadas do Thread: Fornece informações cruciais sobre a pilha para o thread. Este é o local onde podemos ver os bloqueios obtidos pelo Thread e se ele está esperando por algum bloqueio.

Isso é tudo para o thread dump em java.

Source:
https://www.digitalocean.com/community/tutorials/java-thread-dump-visualvm-jstack-kill-3-jcmd