Java Thread Dump – VisualVM, jstack, kill -3, jcmd

Дамп потока Java – это список всех активных потоков в виртуальной машине Java.

Дамп потока Java

Дамп потока Java очень полезен для анализа узких мест в приложении и ситуаций взаимной блокировки. Здесь мы узнаем несколько способов генерации дампа потока для программы на Java. Эти инструкции действительны для операционных систем *nix, но на Windows шаги могут отличаться.

  1. Профилировщик VisualVM: Если вы анализируете приложение на предмет замедления, вам следует использовать профилировщик. Мы можем легко сгенерировать дамп потока для любого процесса с помощью профилировщика VisualVM. Вам просто нужно щелкнуть правой кнопкой мыши на выполняющемся процессе и выбрать опцию “Thread Dump” для его создания.
  2. jstack: В Java есть инструмент jstack, с помощью которого мы можем сгенерировать дамп потока для процесса на Java. Это двухэтапный процесс.
    1. Определите PID процесса Java с помощью команды ps -eaf | grep java
    2. Запустите инструмент jstack, как jstack PID, чтобы сгенерировать вывод дампа потока в консоль. Вы можете добавить вывод дампа потока в файл с помощью команды “jstack PID >> mydumps.tdump
  3. Можно использовать команду kill -3 PID для генерации дампа потоков. Этот способ немного отличается от других способов генерации дампа потоков. При выполнении команды kill дамп потоков генерируется в System out программы. Таким образом, если это java-программа с консолью в качестве System out, дамп потоков будет выведен на консоль. Если java-программа является сервером Tomcat с System out как catalina.out, то дамп потоков будет сгенерирован в файле.
  4. Java 8 ввел утилиту jcmd. Если вы используете Java 8 или выше, лучше использовать ее вместо jstack. Команда для генерации дампа потоков с помощью jcmd: jcmd PID Thread.print.

Вышеописаны четыре различных способа генерации дампа потоков в java. Обычно я предпочитаю использовать команду jstack или jcmd для генерации и анализа дампа потоков. Обратите внимание, что каким бы способом вы ни выбрали, дамп потоков всегда будет одинаковым.

Пример дампа потоков Java

В моем последнем посте я объяснил о java Timer, вот дамп потоков, сгенерированный для этой же программы.

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

Дамп потоков – это список всех потоков, каждая запись содержит информацию о потоке, включая следующее в порядке появления.

  1. Имя потока: Имя потока
  2. Приоритет потока: Приоритет потока
  3. Идентификатор потока: Представляет уникальный идентификатор потока
  4. Статус потока: Предоставляет текущее состояние потока, например, RUNNABLE, WAITING, BLOCKED. При анализе взаимной блокировки ищите заблокированные потоки и ресурсы, на которые они пытаются получить блокировку.
  5. Стек вызовов потока: Предоставляет важную информацию о стеке для потока. Это место, где мы можем увидеть блокировки, полученные потоком, и если он ожидает какую-либо блокировку.

Вот и все для дампа потоков в Java.

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