线上故障排查(二)——高MEM占用

1. 高内存占用

线上故障排查(一)——高CPU占用一文中介绍了高 CPU 占用程序的排查,今天我们介绍高MEM占用的程序。高内存占用的程序是指内存消耗比较大的程序。我们在开发 Java 应用程序的时候,一定见过 OOM(即 java.lang.OutOfMemoryError)。在 JVM 内存模型中,Java 虚拟机栈、本地方法栈、Java 堆、方法区(JDK8 之后是元空间,取消了永久代)都会发生 OOM。

对于 OOM 的解决方案不是本文要阐述的,但是如果能定位程序中哪里导致内存使用过多,也可以从一定层面避免 OOM。

2. 线上排查

同上一篇一样,我主要介绍在服务器上,如何使用 Linux 和 Java 命令去定位导致内存使用过多的原因。以下面程序为例:

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

public class Memory {
    public static void main(String[] args){
        Executor executor = Executors.newFixedThreadPool(5);

        Task task1 = new Task();
        Task task2 = new Task();
        executor.execute(task1);
        executor.execute(task2);
    }
}

class Task implements Runnable{
    @Override
    public void run() {
        synchronized (Runnable.class){
            compute();
        }
    }

    private void compute(){
        try {
            while (true) {
                byte[] bytes = new byte[1024 * 1024 * 500];
                Thread.sleep(1000 * 10);
            }
        }catch (InterruptedException ie){
            ie.printStackTrace();
        }
    }
}

示例程序很简单,循环创建 byte 数组来占用内存。

2.1 使用 top 查看状态

毋庸置疑,查看机器资源的时候,我们首先想到的是 top 命令。对于示例程序,运行之后,不会立即看到内存使用飙升,可能需要等一会儿才可以看到内存的使用比较大,如:
在这里插入图片描述
可以看到 70912 进程的内存使用率达到了 7.4%。

2.2 jmap 查看内存信息

之前我们用 ps 定位过线程 CPU 的使用情况,这里我们先用 ps 再看看该进程中的线程信息:
在这里插入图片描述
可以看到,ps 查不到指定进程中线程使用内存的任何信息。

但是,JDK 的内置工具中有一个 jmap(Java Memory Map) 命令可以查看 Java 进程的内存信息,这里用两个参数可以使用:

  1. jmap -dump:[live,]format=b,file=[filename] PID:使用 hprof 二进制形式,输出 JVM 的 Heap 内容到文件中。live 子选项是可选的,假如指定 live 选项,那么只输出活的对象到文件。导出的文件,可以用专门的内存分析工具来分析,如 Eclipse Memory Analyzer Tool(MAT)
  2. jmap -histo[:live] PID:打印每个 Class 的实例数目,内存占用,类全名信息。JVM 的内部类名字开头会加上前缀 *(星号)。如果 live 子参数加上后,只统计活的对象数量。

我们这里只讨论在服务器上定位,使用命令 jmap -histo:live 70912 > mem.log 命令将该进程的内存信息导入到 mem.log 文件中,如:在这里插入图片描述
这里简单介绍几个 class name:

  • [C:指 char[]。Java 中 String 内部使用 final char[] 来保存数据的。
  • [S:指 short[]。
  • [I:指 int[]。
  • [B:指 byte[]。
  • [[I: 指 int[][]。

从导出的文件中,我们发现 [B 占用的内存比较最多,也就是 byte[] 数组占用的内存最多。然后,我们通过定位示例程序中哪里创建了过多的 byte[] 数组,不难发现是第 26 行代码。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值