jmap+MAT实战内存溢出

博客主要围绕Java内存溢出问题展开。先介绍堆区和非堆区内存溢出的可能原因,如内存泄漏或分配不足,还说明了导出内存映像文件的自动和手动方法。接着讲解用MAT分析dump文件,最后通过Spring Boot项目案例演示内存溢出的构造、导出及分析,给出解决方案。

一、堆区和非堆区

前言:
如果发生内存溢出,主要是通过内存映像文件,来查看到底是那些类,一直在占有没有释放。

  • 1.1 情况分析:

第一种内存溢出:有可能内存泄漏
第二种内存溢出:也有可能内存分配不足导致的

假若:内存泄漏,我们要找到是那个地方把它泄露出去了,一直占有没有释放。
java中的内存泄漏:指new了一个对象之后,一直不释放,这样的内存

  • 1.2 如何导出内存映像文件?
    • 1.2.1 内存溢出JVM自动导出:

当发生内存溢出的时候让jvm自动导出
设置参数:
#当发生内存溢出的时候,把HeapDump导出

-XX:+HeapDumpOnOutOfMemoryError

#当发生内存溢出的时候,把HeapDump出来的路径

-XX:HeapDumpPath=./
  • 1.2.2 使用jmap命令手动导出:

当发生内存溢出的时候,再去dump就有点晚了,当成程序运行一点时间后,我们用jmap手动导出内存映像文件,来具体分析:
执行命令:

jmap -dump:format=b,file=heap.hprof 3456

格式:jmap -dump:format=b,file=heap.hprof pid
命令行输出:

Dumping heap to C:\Users\Administrator.PC-20180929LWLP\Desktop\heap.hprof ...
Heap dump file created

看到以上提示,说明导出成功!!!

二、MAT分析dump文件

打开dump文件

三、案例演示

框架springboot
在浏览器地址栏输入:https://start.spring.io/

  • 3.1 生成一个springboot项目
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 3.2 解压压缩包
  • 3.3 在STS或eclipse或idea导入解压的项目
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 3.4创建一个MemoryController和User对象

实现原理:
因为controller不被回收,它里面的成员变量也 是不会被被回收的,这样就是导致list里面的对象越来越多,占得内存会越来越大,这样就会把我们这个内存撑爆了。

构造内存溢出
1.定义一个 list
2.通过一个循环不停地往这个list里面添加对象
在这里插入图片描述
3.5 启动项目,添加参数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
浏览器验证:
http://localhost:8080/heap

控制台输出:
Exception in thread “http-nio-12345-exec-3” java.lang.OutOfMemoryError: GC overhead limit exceeded
模拟内存溢出自动导出:
在这里插入图片描述

-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./

注:./指项目根目录
控制台输出:
在这里插入图片描述
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to ./\java_pid12468.hprof …
Heap dump file created [44843683 bytes in 0.270 secs]
在这里插入图片描述
mat分析dump文件:
mat下载地址:
https://www.eclipse.org/mat/downloads.php
在这里插入图片描述
在这里插入图片描述
双击打开
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

很明显在MemoryController中,有一个userList,在userList中User对象很多都没有释放。

CPU 线程 线程分析:
在这里插入图片描述
在这里插入图片描述
结果已经很明显了,解决方案就是:释放对象User就可以了
模拟使用jmap命令手动导出:

总结:理论上说:这2中都可以用,当内存很大的时候自动导出会导不出来,建议使用jmap手动导出即可

jmap -heap 3456
可以看到那一块具体用了多少

上面是导出内存映像文件,下面来用MAT
分析内存溢出,内存映像文件到底存了什么东西?如何利用内存映像文件来定位内存溢出呢?
https://www.eclipse.org/downloads/download.php

jstack pid > pid.txt
sz pid.txt
线程状态
top -p 15764 -H
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr034.html

多么痛的领悟-代码优化导致的BUG
blog.csdn.net/goldenfish1919/article/details/8755378

nohup java -jar monitor_tuuning-0.0.1-SNAPSHOT.jar &

10.5.6.142:12345/loop
top命令查看cpu负载,load acerage:
cpu负载变大请求就进不来了
解决方案:
jstack pid > pid pid.txt
sz pid.txt :下载命令

top -p pid -H:打印所有线程,筛选出占用cpu比较多的线程,看看占用cpu线程在干什么?
printf “%x” pid :线程pid
命令行pid是十进制的,导出的jstack 文件时十六进制的
10.5.6.142/deadlock
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.5.6.120"

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.5.6.120"

nohup java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=10.5.6.120 -jar monitor_tuuning-0.0.1-SNAPSHOT.jar &

tail -f nohup.out
jmap手动导出内存映像文件
命令行执行:
jmap -dump:format=b,file=heap.hprof 3456
格式:jmap -dump:format=b,file=heap.hprof pid
[root@localhost ~]# cd /app/nmonlogs/
[root@localhost nmonlogs]# ./nmon
按c查看CPU使用信息,按m查看内存使用信息,按n查看网络使用信息
c
jmap -dump:format=b,file=heap.hprof 31322

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gblfy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值