Java中的CPU占用高和内存占用高的问题排查

共 4181字,需浏览 9分钟

 ·

2021-03-03 11:01

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

  作者 |  归去来兮辞

来源 |  urlify.cn/MBjaAz

76套java从入门到精通实战课程分享

下面通过模拟实例分析排查Java应用程序CPU和内存占用过高的过程。如果是Java面试,这2个问题在面试过程中出现的概率很高,所以我打算在这里好好总结一下。

1、Java CPU过高的问题排查

举个例子,如下: 

package com.classloading;
public class Test {
    static class MyThread extends Thread {
        public void run() { // 死循环,消耗CPU
            int i = 0;
            while (true) {
                i++;
            }
        }
    }
    public static void main(String args[]) throws InterruptedException {
        new MyThread().start();
        Thread.sleep(10000000);
    }
}

使用top命令查看占用CPU过高的进程。如下图所示。

  

查看进程6102下线程的占用情况,如下图所示。

 

使用如下命令将6122转换为16进制表示,如下:

 

导出CPU占用高进程的线程栈。命令如下:


jstack pid >> java.txt 
 
Attaching to remote server pid, please wait...
2021-02-23 15:38:18
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.192-b12 mixed mode):
 
"Attach Listener" #10 daemon prio=9 os_prio=0 tid=0x00007f4ee0001000 nid=0x1956 runnable [0x0000000000000000]
   java.lang.Thread.State: RUNNABLE
// 这是0x17ea线程,也是占用CPU最高的线程
"Thread-0" #9 prio=5 os_prio=0 tid=0x00007f4f180d6000 nid=0x17ea runnable [0x00007f4f044da000]
   java.lang.Thread.State: RUNNABLE
    at com.cpuhigh.Test$MyThread.run(Test.java:8)  // 这里指示第8行,则正是死循环的代码开始
 
...

内容如下:  

导出的堆栈信息有线程的状态(一般要找RUNNABLE状态)和调用堆栈结合来查找问题。线程dump分析:线程dump分析主要目的是定位线程长时间停顿的原因 

2、Java 内存过高的问题排查 

举个例子如下:

package com.classloading;
 
import java.util.ArrayList;
import java.util.List;
 
public class Test {
    private static final int UNIT_MB = 1024 * 1024;
     
    public static void main(String args[]) throws InterruptedException{
        List<Object> x = new ArrayList<Object>();
        int i = 0;
        while(i<1000){
            x.add(new byte[UNIT_MB]);
            i++;
        }
        Thread.sleep(1000000000);
    }
}

通过jmap dump内存快照。如果是线上环境,注意dump之前必须先将流量切走,否则大内存dump是直接卡死服务。

命令行输入:


jmap -histo <pid> | head -20


 就可以查看某个pid的java服务占用内存排名前20的类,如下图所示。

可以看到,占用内存最多的是byte字节数组,共有1008个实例。

jmap还有一个指令可以把整个内存情况转成文件形式保存下来,如下:

jmap -dump:format=b,file=filename.bin <pid>

 执行命令如下图所示。

可以在JVM启动时设置,如果发生OOM,则dump出文件。命令如下:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heapdump.hprof
jmap -dump:format=b,file=filename.bin <pid>

如果快照文件不大,可以下载到本地,然后通过MAT分析,也可以在线分析(https://fastthread.io/);如果快照文件很大,可以在服务器上直接分析,使用的命令是:

jhat dump.hprof

jhat也是jdk内置的工具之一。主要是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询语言。命令执行后如下图所示。

 

访问如下图所示。

其中的Show heap histogram就会显示对象占用内在的大小。如下图所示。 

 

 

 


粉丝福利:Java从入门到入土学习路线图

👇👇👇

👆长按上方微信二维码 2 秒


感谢点赞支持下哈 

浏览 25
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报