一、命令介绍
Usage:
jstack [-l] <pid>
(to connect to running process) //连接活动线程
jstack -F [-m] [-l] <pid>
(to connect to a hung process) //连接阻塞线程
jstack [-m] [-l] <executable> <core>
(to connect to a core file) //连接dump的文件
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server) //连接远程服务器
Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message
二、使用实例
要使用jstack命令,首先我们要先找到要查看的进程ID,命令如下:
$ ps -ef | grep --color "com.javaagent.Main"
结果如下:
红框中即为进程ID。
实例一:jstack查看输出
命令如下:
$ jstack -l 69239
输出结果:
$ jstack -l 69239
2020-03-03 15:16:07
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.121-b13 mixed mode):
"Attach Listener" #13 daemon prio=9 os_prio=31 tid=0x00007f9242141000 nid=0x5707 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"ThreadTest" #11 prio=5 os_prio=31 tid=0x00007f9242140800 nid=0x5503 waiting on condition [0x00007000013d2000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at com.javaagent.Main$2.run(Main.java:64)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
...
"ThreadTest_2" #10 prio=5 os_prio=31 tid=0x00007f9242100000 nid=0x5303 in Object.wait() [0x00007000012cf000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000795856e18> (a java.lang.Object)
at java.lang.Object.wait(Object.java:502)
at com.javaagent.Main$1.run(Main.java:41)
- locked <0x0000000795856e18> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007f9242004000 nid=0x3003 in Object.wait() [0x000070000092e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x0000000795588ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)
- locked <0x0000000795588ec8> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
Locked ownable synchronizers:
- None
"VM Thread" os_prio=31 tid=0x00007f9243841800 nid=0x2c03 runnable
"GC task thread#0 (ParallelGC)" os_prio=31 tid=0x00007f9243810800 nid=0x2403 runnable
"GC task thread#1 (ParallelGC)" os_prio=31 tid=0x00007f9243811000 nid=0x2603 runnable
"GC task thread#2 (ParallelGC)" os_prio=31 tid=0x00007f9243811800 nid=0x2803 runnable
"GC task thread#3 (ParallelGC)" os_prio=31 tid=0x00007f9243812800 nid=0x2a03 runnable
"VM Periodic Task Thread" os_prio=31 tid=0x00007f9243805000 nid=0x4d03 waiting on condition
JNI global references: 25
实例二:jstack统计线程数
命令如下:
$ jstack -l 69239 | grep 'java.lang.Thread.State' | wc -l
输出结果:
12
实例三:jstack检测死锁
死锁代码:
package com.javaagent.thread;
public class DieThread implements Runnable {
public static Object obj1=new Object();
public static Object obj2=new Object();
private boolean flag;
public DieThread(boolean bl){
flag = bl;
}
@Override
public void run() {
if(flag) {
while(true) {
synchronized(obj1) {
System.out.println(Thread.currentThread().getName()+"....if...obj1...");
synchronized(obj2) {
System.out.println(Thread.currentThread().getName()+".....if.....obj2.....");
}
}
}
}
else {
while(true){
synchronized(obj2) {
System.out.println(Thread.currentThread().getName()+"....else...obj2...");
synchronized(obj1) {
System.out.println(Thread.currentThread().getName()+".....else.....obj1.....");
}
}
}
}
}
}
public class Main {
public static void main(String[] args){
DieThread d1=new DieThread(true);
DieThread d2=new DieThread(false);
final Thread t1 = new Thread(d1);
final Thread t2 = new Thread(d2);
t1.setName("DieThread_1");
t2.setName("DieThread_2");
t1.start();
t2.start();
}
}
命令如下:
$ jstack -l 69239
死锁日志:
"DieThread_2" #11 prio=5 os_prio=31 tid=0x00007fc761896000 nid=0x5503 waiting for monitor entry [0x000070000134f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.javaagent.thread.DieThread.run(DieThread.java:32)
- waiting to lock <0x000000079586a768> (a java.lang.Object)
- locked <0x000000079586a778> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"DieThread_1" #10 prio=5 os_prio=31 tid=0x00007fc7610dd800 nid=0x5307 waiting for monitor entry [0x000070000124c000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.javaagent.thread.DieThread.run(DieThread.java:21)
- waiting to lock <0x000000079586a778> (a java.lang.Object)
- locked <0x000000079586a768> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
Found one Java-level deadlock:
=============================
"DieThread_2":
waiting to lock monitor 0x00007fc7620421f8 (object 0x000000079586a768, a java.lang.Object),
which is held by "DieThread_1"
"DieThread_1":
waiting to lock monitor 0x00007fc762042358 (object 0x000000079586a778, a java.lang.Object),
which is held by "DieThread_2"
Java stack information for the threads listed above:
===================================================
"DieThread_2":
at com.javaagent.thread.DieThread.run(DieThread.java:32)
- waiting to lock <0x000000079586a768> (a java.lang.Object)
- locked <0x000000079586a778> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
"DieThread_1":
at com.javaagent.thread.DieThread.run(DieThread.java:21)
- waiting to lock <0x000000079586a778> (a java.lang.Object)
- locked <0x000000079586a768> (a java.lang.Object)
at java.lang.Thread.run(Thread.java:745)
Found 1 deadlock.
实例四:jstack检测CPU高
步骤一:查看cpu占用高进程
输入命令:
$ top
输出结果:
top - 07:50:58 up 53 days, 23:38, 2 users, load average: 0.00, 0.00, 0.00
Tasks: 113 total, 1 running, 112 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 7771904k total, 1770024k used, 6001880k free, 160496k buffers
Swap: 1048572k total, 0k used, 1048572k free, 844572k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
9075 root 20 0 19468 1540 1116 R 0.7 0.0 0:00.02 top
1177 root 20 0 240m 4252 1688 S 0.3 0.1 176:47.24 oneagentwatchdo
1546 zabbix 20 0 81212 1616 728 S 0.3 0.0 28:12.55 zabbix_agentd
4433 root 20 0 4495m 566m 14m S 0.3 7.5 61:48.80 java
1 root 20 0 23804 1772 1364 S 0.0 0.0 0:00.82 init
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root RT 0 0 0 0 S 0.0 0.0 0:03.89 migration/0
4 root 20 0 0 0 0 S 0.0 0.0 0:16.97 ksoftirqd/0
步骤二:查看cpu占用高线程
输入命令:
$ top -H -p 4433
输出结果:
top - 07:52:22 up 53 days, 23:40, 2 users, load average: 0.08, 0.02, 0.01
Tasks: 62 total, 0 running, 62 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.1%us, 0.1%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 7771904k total, 1770296k used, 6001608k free, 160496k buffers
Swap: 1048572k total, 0k used, 1048572k free, 844576k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4433 root 20 0 4495m 566m 14m S 0.0 7.5 0:00.00 java
4434 root 20 0 4495m 566m 14m S 0.0 7.5 0:09.75 java
4435 root 20 0 4495m 566m 14m S 0.0 7.5 0:00.99 java
4436 root 20 0 4495m 566m 14m S 0.0 7.5 0:01.00 java
4437 root 20 0 4495m 566m 14m S 0.0 7.5 2:10.19 java
4438 root 20 0 4495m 566m 14m S 0.0 7.5 0:00.08 java
4439 root 20 0 4495m 566m 14m S 0.0 7.5 0:00.07 java
4440 root 20 0 4495m 566m 14m S 0.0 7.5 0:00.00 java
4441 root 20 0 4495m 566m 14m S 0.0 7.5 0:06.90 java
4446 root 20 0 4495m 566m 14m S 0.0 7.5 1:10.37 java
4447 root 20 0 4495m 566m 14m S 0.0 7.5 0:04.77 java
4448 root 20 0 4495m 566m 14m S 0.0 7.5 0:56.77 java
步骤三:转换线程ID
printf "%x\n" 4434 //转换成16进制
输出结果:
1152 //16进制
步骤四:定位cpu占用线程
输入命令:
$ jstack 4433 | grep 1152 -A 30
说明:
- 4433:进程ID;
- 1152:线程16进制ID;
输出结果:
"main" #1 prio=5 os_prio=0 tid=0x00007f3b5c00b800 nid=0x1152 runnable [0x00007f3b61c8d000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at org.apache.catalina.core.StandardServer.await(StandardServer.java:470)
at org.apache.catalina.startup.Catalina.await(Catalina.java:793)
at org.apache.catalina.startup.Catalina.start(Catalina.java:739)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:428)
"VM Thread" os_prio=0 tid=0x00007f3b5c0fc000 nid=0x1155 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007f3b5c020800 nid=0x1153 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007f3b5c022800 nid=0x1154 runnable
"VM Periodic Task Thread" os_prio=0 tid=0x00007f3b5cad6000 nid=0x117d waiting on condition
JNI global references: 262