JVM: 使用 jstack 命令找出 cpu 飙高的原因

首先新建一个springboot项目,新建一个controller

@RestController public class DeadLockController {private Object lock1 = new Object(); private Object lock2 = new Object(); @GetMapping("/deadlock") public String deadLock() { new Thread(() -> { synchronized (lock1) { try { Thread.sleep(1000); } catch (Exception e) { } synchronized (lock2) { System.out.println("Thread1 over"); } } }).start(); new Thread(() -> { synchronized (lock2) { try { Thread.sleep(1000); } catch (Exception e) { } synchronized (lock1) { System.out.println("Thread2 over"); } } }).start(); return "deadlock"; }@RequestMapping("/loop") publicListloop() { String data = "https://www.it610.com/article/{/"data\":[{\"partnerid\":]"; return getPartneridsFromJson(data); }public static List getPartneridsFromJson(String data){ List list = new ArrayList(2); if(data =https://www.it610.com/article/= null || data.length() <= 0){ return list; } int datapos = data.indexOf("data"); if(datapos < 0){ return list; } int leftBracket = data.indexOf("[",datapos); int rightBracket= data.indexOf("]",datapos); if(leftBracket < 0 || rightBracket < 0){ return list; } String partners = data.substring(leftBracket+1,rightBracket); if(partners == null || partners.length() <= 0){ return list; } while(partners!=null && partners.length() > 0){ int idpos = partners.indexOf("partnerid"); if(idpos < 0){ break; } int colonpos = partners.indexOf(":",idpos); int commapos = partners.indexOf(",",idpos); if(colonpos < 0 || commapos < 0){ continue; } String pid = partners.substring(colonpos+1,commapos); if(pid == null || pid.length() <= 0){ continue; } try{ list.add(Long.parseLong(pid)); }catch(Exception e){ } partners = partners.substring(commapos); } return list; }}

使用maven把项目打成jar包,然后使用命令:nohup java -jar springboot-0.0.1-SNAPSHOT.jar & 运行项目
先测试死循环,打开地址:http://192.168.0.8:8080/loop ,可以多开几个页面,然后使用top命令查看
JVM: 使用 jstack 命令找出 cpu 飙高的原因
文章图片

可以看到进程5700的cpu飙到快700, load average也一直在 不停上升。
使用命令:
jstack 5700 > 5700.txttop -p 5700 -H//查看5700进程的所有线程

JVM: 使用 jstack 命令找出 cpu 飙高的原因
文章图片

可以看到5732、5735、5729 等好几个线程cpu都飙到了99%,我们可以看一下 5700.txt中,这些线程在干什么 。以5732为例,由于5700.txt文本中的进程号都是16进制的,而5732是十进制,所以我们把5732转16进制得到1664。去5700.txt中查找1664,执行命令 grep -C 10 "1664" 5700.txt
JVM: 使用 jstack 命令找出 cpu 飙高的原因
文章图片

这样可以很清晰的看到是我们的DeadLockController里面的方法造成的。
【JVM: 使用 jstack 命令找出 cpu 飙高的原因】再测试死锁,先把上一个项目进程关掉,执行命令 kill -9 5700,再重新运行项目
打开 http://192.168.0.8:8080/deadlock
在执行命令,用jstack打印出进程的线程堆栈信息,如重启项目后的进程号是8208,jstack 8208 > 8208.txt
查看 8208.txt cat 8208.txt
JVM: 使用 jstack 命令找出 cpu 飙高的原因
文章图片

可以看到,文件里面已经找到了一处死锁

    推荐阅读