运维技能 之 Java内存溢出Out Of Memory原因排查

1、前言

生产环境中,我们可能会遇到Java内存溢出Out Of Memory。此时我们可以借助内存分析工具MAT(Memory Analyzer Tool),来定位是哪里出现了问题。

2、MAT独立程序的下载安装

MAT(Memory Analyzer Tool)下载地址:http://www.eclipse.org/mat/downloads.php
在这里插入图片描述

在这里插入图片描述

根据自己的安装环境,选择操作系统和JDK对应的MAT版本,我这里选择的是Windows (x86_64)。下载好的压缩包解压到本地任意一个文件夹里,然后就可以开始使用了(MAT运行环境需要依赖JDK)。下图是我的解压路径,圈注的就是启动MAT程序执行文件。
在这里插入图片描述

解压后目录内有个MemoryAnalyzer.ini文件,该文件里面有个-Xmx参数。该参数表示最大内存占用量,默认为1024m。
建议修改为小于本机内存大小,大于要分析的dump文件大小

-startup
plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.700.v20180518-1200
-vmargs
### -Xmx1024my原本默认为1024m,此处我修改为4096m
-Xmx4096m

3、得到一个内存溢出的dump

如何生成dump文件,有主动和被动两种方式。我们先启动一个准备好的Springboot程序

package com.wzl.xman.servicea.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class MemoryController {

    private static List list = new ArrayList<Byte[]>();

    @GetMapping(value = "/oom/{size}")
    public String outOfMemoryTest(@PathVariable(value = "size") Long size) {
    	//根据传入size的大小,可能会引起OOM内存溢出
        for (int i = 0; i < size; i++) {
            Byte[] bytes = new Byte[1024];
            list.add(bytes);
        }
        return "ok";
    }

}
nohup java -jar -server -Xms256m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/oom/heapdump.hprof xman-service-a-0.0.1-SNAPSHOT.jar &

3.1、主动方式

主动生成dump文件,首先查找运行的Java程序的PID,可用top或者ps命令查找。

###top命令找资源消耗最高的
top
###ps命令精确查找java进程
ps -ef|grep java

在这里插入图片描述

在这里插入图片描述

然后使用jmap命令生成dump文件,file后面是dump文件的保存路径名称,2033则是java程序的PID

jmap -dump:format=b,file=/opt/oom/heapdump.hprof 2033

在这里插入图片描述

在这里插入图片描述

注意:主动获取dump文件必须是一出现内存异常就获取dump文件,这样获取的文件信息才比较准确。如果无法及时获取,推荐通过第二种方式获取dump文件。

3.2、被动方式

  • 被动方式就是在程序启动的时候增加了参数:
    -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/oom/heapdump.hprof
  • 在JVM出现内存溢出的情况下,JVM会自动生成dump文件
nohup java -jar -server -Xms256m -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/oom/heapdump.hprof xman-service-a-0.0.1-SNAPSHOT.jar &

敲击一个会导致内存溢出的请求:http://192.168.12.11:31002/oom/1000000

在这里插入图片描述

此时应用宕机,生成.hprof文件

4、MAT工具对dump文件的分析

我们分析通过被动方式生成测dump文件

  • 启动MAT工具,选择File – Open Heap Dump…,导入dump文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

红色部分是我们要重点看的,接下来我们看Details:

在这里插入图片描述
在这里插入图片描述

  • 可以看到MemoryController类中存在一个ArrayList集合,存放了大量的new Byte[1024]数据。光这一个对象就占用总大小的94.6%,这就是问题的根源,然后就可以分析代码存在的问题了。
  • 更多MAT的使用方式,请自行百度
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值