一、根据 Java 进程 ID,用 ps
或 top
命令查询出 CPU 占用率高的线程
1 | ps -mp <pid> -o THREAD,tid,time | sort -rn | more // (sort -rn 已数值的方式进行逆序排列) |
二、转换线程 ID 为 16 进制
1 | printf "%x\n" <tid> |
三、利用 JDK 提供的工具 jstack
打印导出线程信息
1 | jstack <pid> | grep <16tid> -A 30 // 或导出 jstack <pid> >> jstack.txt 文件查看 |
四、查看线程信息并处理
4.1 如果是用户线程
查看相关代码并处理
附 jstack
死锁日志
4.2 如果是 Full GC 次数过多
1 | "main" #1 prio=5 os_prio=0 tid=0x00007f8718009800 nid=0xb runnable [0x00007f871fe41000] |
nid=0xa 为系统线程 ID
使用 JDK 提供的工具 jstat
查看 GC 情况
1 | jstat -gcutil <pid> 1000 10 |
使用 JDK 提供的 jmap
工具导出内存日志到 Eclipse mat工具进行查看
1 | // 简单查看存活对象的大小数目 |
主要有以下两种原因:
- 代码中一次获取了大量的对象,导致内存溢出
- 内存占用不高,但是 Full GC 次数还是比较多,此时可能是显示的
System.gc()
调用导致 GC 次数过多,这可以通过添加-XX:+DisableExplicitGC
来禁用JVM对显示GC的响应
总结
通过 ps
或 top
命令找出 CPU 过高的线程,将其线程 ID 转换为十六进制,然后在 jstack
日志中查看该线程信息,分为以下两种情况:
- 如果是正常的用户线程,则通过该线程的堆栈信息查看其具体是在哪处用户代码处运行比较消耗 CPU
- 如果该线程是 VM Thread 则通过
jstat -gcutil <pid> <period> <times>
命令监控当前系统的 GC 状况,然后通过jmap dump:format=b,file=<filepath> <pid>
导出系统当前的内存数据,导出之后将内存情况放到 eclipse 的 mat 工具中进行分析即可得出内存中主要是什么对象比较消耗内存,进而可以处理相关代码
参考链接: