Thread Dump
References:
- http://javaeesupportpatterns.blogspot.com/2012/07/how-to-analyze-thread-dump-part-5.html
- http://javaeesupportpatterns.blogspot.com/2012/02/how-to-analyze-thread-dump-part-3.html
- https://www.javacodegeeks.com/2012/03/jvm-how-to-analyze-thread-dump.html
从Thead Dump找出Java线程所对应的OS进行或线程,以能在OS层面观察该线程(CPU/Memory)
从Java Thread到OS Thread
./jstack -l <PID_OF_JAVA>
上面命令的输出就是Java虚拟机中的所有线程信息。对于每一个线程,你可以看到他都有一个nid(native thread id),代表的就是系统的进程ID。我们可以看到,下面的输出中,线程"pool-30-thread-10"的nid是0x47c3=18371, 你可以在OS层面,去观察进程18371的信息和状态。
2017-02-22 13:05:18
Full thread dump Java HotSpot(TM) Server VM (25.111-b14 mixed mode):
"Attach Listener" #330 daemon prio=9 os_prio=0 tid=0x08330000 nid=0x3a24 waiting on condition [0x00000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"pool-30-thread-10" #321 prio=5 os_prio=0 tid=0x0a9ac000 nid=0x47c3 waiting on condition [0xc5a74000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0xd89e1e10> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
at java.util.concurrent.LinkedBlockingQueue.take(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.getTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Locked ownable synchronizers:
- None
观察进程18371的信息,常见的方法是用top或者/proc/<pid>/status
top -p 18371
cat /proc/18371/status
Name: java
State: S (sleeping)
Tgid: 22904
Ngid: 0
Pid: 18371
PPid: 1
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 512
...
从OS进程到Java Thread
假设我们只知道进程号18371, 然后去看/proc/18371/status, 我们会看到Name: java, Tgid: 22904,22904可能就是JVM的主进程号。