首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线上CPU飚高(死循环,死锁...)?帮你迅速定位代码位置

线上CPU飚高(死循环,死锁...)?帮你迅速定位代码位置

作者头像
Java识堂
发布2019-08-13 11:21:38
9450
发布2019-08-13 11:21:38
举报
文章被收录于专栏:Java识堂Java识堂

top基本使用

top 命令运行图:

第一行:基本信息

第二行:任务信息

第三行:CPU使用情况

第四行:物理内存使用情况

buff/cache:

buffers 和 cache 都是内存中存放的数据,不同的是,buffers 存放的是准备写入磁盘的数据,而 cache 存放的是从磁盘中读取的数据

在Linux系统中,有一个守护进程(daemon)会定期把buffers中的数据写入的磁盘,也可以使用 sync 命令手动把buffers中的数据写入磁盘。使用buffers可以把分散的 I/O 操作集中起来,减少了磁盘寻道的时间和磁盘碎片。 cache是Linux把读取频率高的数据,放到内存中,减少I/O。Linux中cache没有固定大小,根据使用情况自动增加或删除。

第五行:交换区使用情况

Swap(内存交换区):

  是硬盘上的一块空间。在内存不足的情况下,操作系统把内存中不用的数据存到硬盘的交换区,腾出内存来让别的程序运行。因此,开启swap会一定程度的引起 I/O 性能下降(阿里服务器默认不开)

第六行:进程详细信息

死循环

构造的代码如下:

@RestController
@RequestMapping("top")
public class ShowTopController {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    @RequestMapping("test")
    public String test() {
        return "success";
    }

    @RequestMapping("loop")
    public String loop() {
        System.out.println("start");
        while (true) {}
    }

    @RequestMapping("deadlock")
    public String deadlock() {
        new Thread(() -> {
            synchronized (lock1) {
                try{
                    TimeUnit.SECONDS.sleep(1);
                } catch (Exception e) {}
                synchronized (lock2) {
                    System.out.println("thread1 over");
                }
            }
        }).start();
        new Thread(() -> {
            synchronized (lock2) {
                try{
                    TimeUnit.SECONDS.sleep(1);
                } catch (Exception e) {}
                synchronized (lock1) {
                    System.out.println("thread2 over");
                }
            }
        }).start();
        return "success";
    }
}

这里只介绍一下用到的top参数

先手动制造CPU飙高的场景,多执行几次,小编这里执行3次

curl localhost:8080/top/loop

执行top

jstack命令工具可以得到线程堆栈信息,根据这些线程堆栈信息,我们可以去检查Java程序出现的问题

看到pid为23757的进程CPU占用较高,执行如下命令

jstack 23757 > loop.txt

看看pid为23757的进程中线程的具体情况

top -p 23757 -H

当然你也可以使用交互命令

top -p 23757

然后再输入H,效果和上面一样

可以看到PID为23772,23773和23774的线程占用CPU较高

这里可能有人有疑惑,为什么线程也有PID啊?其实线程进程都会有自己的ID,这个ID就叫做PID,PID是不特指进程ID,线程ID也可以叫做PID

将10进制的23772转为16进制,因为jstack中PID用的是16进制

printf "%x" 23772
输出5cdc

打开loop.txt文件,搜5cdc

可以看到线程一直在执行ShowTopController中的第23行,即

while (true) {}

好了定位到代码中的位置了,当然生产环境中肯定不会写一个死循环的,有可能在特殊场景下出现死循环,或执行一个方法特别慢,用这种方法很快就能找到代码位置。

死锁

接着访问

curl localhost:8080/top/loop

执行

jstack 23757 > loop.txt

打开loop.txt文件到最后

看到发现一个死锁,死锁代码的位置描述的很清楚,生产环境发生的死锁当然没有这么简单,所有学会用这些命令排查还是很有必要的

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java识堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • buff/cache:
  • Swap(内存交换区):
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档