Java线程转储 – VisualVM、jstack、kill -3、jcmd

Java线程转储是JVM中所有活动线程的列表。

Java线程转储

Java线程转储在分析应用程序中的瓶颈和死锁情况方面非常有帮助。在这里,我们将学习通过多种方式为Java程序生成线程转储。这些说明适用于*nix操作系统,但在Windows中,步骤可能会有些不同。

  1. VisualVM Profiler:如果您正在分析应用程序的运行缓慢,您必须使用分析器。我们可以使用VisualVM分析器轻松为任何进程生成线程转储。您只需右键单击运行中的进程,然后单击“Thread Dump”选项即可生成它。
  2. jstack:Java带有jstack工具,通过它我们可以为Java进程生成线程转储。这是一个两步过程。
    1. 使用ps -eaf | grep java命令查找Java进程的PID
    2. jstack PID运行jstack工具,将线程转储输出到控制台,您可以使用命令“jstack PID >> mydumps.tdump”将线程转储输出附加到文件
  3. 我们可以使用kill -3 PID命令生成线程转储。这与其他生成线程转储的方式略有不同。当发出kill命令时,线程转储会生成到程序的System out中。因此,如果是一个将控制台作为系统输出的java程序,线程转储将被打印到控制台上。如果java程序是一个Tomcat服务器,系统输出是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. 线程ID:表示线程的唯一ID
  4. 线程状态:提供当前的线程状态,例如RUNNABLE、WAITING、BLOCKED。在分析死锁时,要查找被阻塞的线程以及它们试图获取锁的资源。
  5. 线程调用堆栈:为线程提供关键的堆栈信息。这是我们可以看到线程获取的锁以及是否正在等待任何锁的地方。

以上就是Java中的线程转储。

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