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")
    public  List<Long>  loop() {
        String data = "{\"data\":[{\"partnerid\":]";
        return getPartneridsFromJson(data);
    }

    public static List<Long> getPartneridsFromJson(String data){
        List<Long> list = new ArrayList<Long>(2);
        if(data == 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命令查看

在这里插入图片描述

可以看到进程5700的cpu飙到快700, load average也一直在 不停上升。

使用命令:

jstack 5700 > 5700.txt

top -p 5700 -H    //查看5700进程的所有线程

在这里插入图片描述

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

在这里插入图片描述
这样可以很清晰的看到是我们的DeadLockController里面的方法造成的。

再测试死锁,先把上一个项目进程关掉,执行命令 kill -9 5700,再重新运行项目
打开 http://192.168.0.8:8080/deadlock
在执行命令,用jstack打印出进程的线程堆栈信息,如重启项目后的进程号是8208,jstack 8208 > 8208.txt
查看 8208.txt cat 8208.txt
在这里插入图片描述
可以看到,文件里面已经找到了一处死锁

猜你喜欢

转载自blog.csdn.net/eaphyy/article/details/84451199