模拟jvm内存溢出并使用mat分析原因

由于我们在生产环境中不能随意打印log日志,也不能随意更新代码重启生产环境的服务,所以当生产环境发生内存溢出时我们应该采取什么措施来找出问题所在尼?

一、模拟内存溢出

@RestController
public class MemoryController {
    private List<User> userList = new ArrayList<User>();
 
    /**
     * -Xmx32M -Xms32M
     * @return
     */
    @GetMapping("/heap")
    public String heap(){
        int i = 0;
        while (true){
            userList.add(new User(i++, UUID.randomUUID().toString()));
        }
    }
}

注释:请求http://localhost:8080/heap,不断往userList中添加User对象,由于userList是MemoryController的属性不会被回收,故导致内存溢出。
在启动时配置jvm参数:-Xmx32M -Xms32M (使得程序尽快能够内存溢出,不用等待很长时间)

二、生成heap dump文件

我们选择以下任意一种方式来获取一份heap dump文件:

1.自动生成

运行前添加jvm参数:
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
当内存溢出时会在当前目录下自动生成heap dump文件

2.手动执行

当发生内存溢出时在控制台手动输入命令: 
jmap -dump:format=b,file=heap.hprof 4063
其中4063为java程序运行的pid,运行命令后会在执行目录下生成heap.hprof文件

三、使用mat工具分析

下载mat(下载地址),下载mac版本,双击运行。
选择我们上面模拟生成的heap dump文件,加载完成后。
首页:
32EEAD9F-7B01-49CA-9ABF-4F9FD4530080.png
点击Leak Suspects查看可能产生泄露的原因:
CE3B40A4-89E6-4EA5-ADA9-914BF3BC6EA3.png

首先怀疑的是MemoryController这个类总共占用了62.26%的内容

点击标题栏第二个按钮,输入包名正则,查看对象在内存中的数量

0FB2950E-DC9D-47DC-86AB-D9E2AA1966B6.png

我们可以看到产生了110476个User对象,可以看出这明显是不正常的现象
下面查看该对象的强引用

D0C498BA-6608-45C2-81FA-26CF44D001A2.png

可以看出MemoryController对象的userList属性中存在110476个User对象,于是我们就找到了内存泄露的真正原因了。

B807622A-A8D5-4578-873C-9921F129B84F.png

我们还可以从对象占用内存比例来查找原因,点击标题栏第三个图标,输入包名正则表达式,可以看到按照内存占用的排序结果,这也同样反应了问题所在

FA7E61FF-0C21-4320-BF18-47BA4219E649.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值