Java线程转储– VisualVM,jstack,kill -3,jcmd
Java线程转储是JVM中所有活动线程的列表。
Java线程转储
Java线程转储对于分析应用程序和死锁情况下的瓶颈非常有帮助。
其中我们将学习多种方法,可以为Java程序生成线程转储。
这些说明对* nix操作系统有效,但在Windows中,步骤可能稍有不同。
VisualVM Profiler:如果要分析应用程序的运行速度,则必须使用Profiler。
我们可以很容易地使用VisualVM Profiler为任何进程生成线程转储。
您只需要右键单击运行的进程,然后单击" Thread Dump"选项即可生成它。jstack:Java附带了jstack工具,通过它我们可以为Java进程生成线程转储。
这是一个两步过程。
使用ps -eaf |查找Java进程的PID。 grep java
命令以jstack PID的身份运行jstack工具以生成线程转储输出到控制台,您可以使用命令" jstack PID >> mydumps.tdump"将线程转储输出附加到文件。
我们可以使用kill -3 PID命令来生成线程转储。
这与生成线程转储的其他方式稍有不同。
当发出kill命令时,线程转储会从程序中生成到系统。
因此,如果它是一个将控制台作为系统输出的Java程序,则线程转储将打印在控制台上。
如果Java程序是Tomcat服务器,系统输出为catalina.out
,则将在文件中生成线程转储。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.theitroad.threads.MyTimerTask.completeTask(MyTimerTask.java:19) at com.theitroad.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.theitroad.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
线程转储是所有线程的列表,每个条目都显示有关线程的信息,其中包括按照出现顺序的信息。
线程名称:线程名称
线程优先级:线程优先级
线程ID:代表线程的唯一ID
线程状态:提供当前线程状态,例如RUNNABLE,WAITING,BLOCKED。
分析死锁时,寻找它们试图获取锁的阻塞线程和资源。线程调用堆栈:提供线程的重要堆栈信息。
其中我们可以看到Thread获得的锁以及是否正在等待任何锁。