jstack(查看线程)、jmap(查看内存)和jstat(性能分析)
1.使用top,查询出最耗内存的cpu对应的pid
/opt/java8/bin/jstack
Usage:
jstack [-l] <pid> 举例:jstack -l 8748
(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
2.查询pid下有多少个线程:jstack -l pid | grep 'java.lang.Thread.State' | wc -l 显示 'java.lang.Thread.State'的行数
举例:jstack -l 8748 | grep 'java.lang.Thread.State' | wc -l --->返回线程数 266
3.把jstack记录保存到文件里 :
cd /log/java/push-service
jstack -l pid >> 123.txt , rz 上传命令,sz 123.txt 下载命令
jstack 12652 | head -100
4.查看当前进程消耗资源的线程pid top -Hp pid
5 将线程Pid转为16进制,根据该16进制值去打印的堆栈日志内查询,查看该线程所驻留的方法位置。
printf "%x\n" 17880
45d8
(基本上这步已经能够定位大多数问题了)
6.所在行的后面30行
[app@push-service42-N-1586391544-1-uc push-service]$ jstack 3608|grep f76 -A 30
"pool-13-thread-1" #234 prio=5 os_prio=0 tid=0x00007fc03c098f40 nid=0xf76 waiting on condition [0x00007fbff3089000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000006c4509b00> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
5 若依然无法定位问题,可以查看堆中对象数量和大小 jmap -histo pid
jmap -histo:live 12240 | head -30 !!!不要随意执行,会垃圾回收
jmap 12652 | head -30 前30行
下载dump文件:
另外可以通过如下命令生成堆dump文件拿到本地通过jdk/bin下自带的jvisualvm.exe打开图形化显示详细的内存信息。
jmap -dump:format=b,file=heapdump pid
jmap -dump:live,format=b,file=dump20191020.hprof 30623
会下载到 /tmp/hsperfdata_app/
format=b指定为二进制格式文件
[app@push-service42-N-1586391544-1-uc push-service]$ jmap -histo 3608 |head -30
num #instances #bytes class name
----------------------------------------------
1: 3881673 476282408 [C
2: 1221885 275547624 [B
3: 10497 78637560 [J
4: 466593 73193440 [I
5: 1052986 69120064 [Ljava.lang.Object;
6: 2123613 50966712 java.lang.String
7: 373472 23329856 [Ljava.util.HashMap$Node;
8: 576545 18449440 java.util.LinkedHashMap$LinkedKeyIterator
9: 418706 16748240 java.util.LinkedHashMap$Entry
10: 338957 16269936 java.nio.HeapByteBuffer
11: 271442 15200752 java.util.LinkedHashMap
12: 632188 15172512 java.util.concurrent.CompletableFuture
13: 190638 12200832 java.util.regex.Matcher
14: 499751 11994024 java.util.ArrayList
15: 361516 11568512 java.util.HashMap$Node
16: 226204 10857792 java.nio.HeapCharBuffer