jvm 内存溢出 Java heap space 调优解决过程

思路清晰,学习如何用jdk工具寻找隐藏bug

----------------------------------------------------------------------------------------------------------------

这里写图片描述

那么:问题来了, 一点自己写的代码的信息没有,怎么找?相信这是大多数兄弟遇到内存问题的第一反应

错误信息是我朋友发给我的截图,我并没有他的代码,也不清楚项目的业务,更不知道为什么会OutOfMemory,懵逼中

 

开始搞事情

首先:理清思路

1. 发现问题

2. 分析问题

3. 解决问题


首先梳理一下思路:

  • OutOfMemory,内存溢出, 是的,溢出了,什么问题导致的呢,是不是程序的内存给的不够引起的呢。

    随即,我问了我的朋友程序启动指定内存没有?如果没有的话制定以下内存会不会解决问题呢

    -Xms512m -Xmx2048m
  • 你以为到这就结束了吗?那未免也太积薄水了吧

    (●’◡’●): 不行呀,兄弟, 我访问没问题了,给我们老板访问就不行了,还是java.lang.OutOfMemoryError: Java heap space,是不是我们老板有毒呀,我是不是考虑要换一个公司呀。

    /(ㄒoㄒ)/: 兄弟,我认真的思考了一下。不瞒你说,我感觉你们老板没有那么简单,最起码也得会个气功什么的,你以后要小心呀!!!(重要的事情三个感叹号)
    (●’◡’●):葵花宝典我已经看完前言了,我离成功就差那么零点零一毫米了,但是现在tmd内存溢出了我肿么办!
    /(ㄒoㄒ)/:兄弟莫着急,你用OutOfMemoryError神器jvisualvm看一下内存情况
    (●’◡’●):那是什么玩意,玉女心经里的么?md我还没看到那呢
    。。。。。。。。。。。。。。。。。。。
    一番神讲解下终于打开jvisualvm查看了内存情况。。。
    该工具位于jdk安装目录下bin目录下,是jdk自带分析工具,功能非常强大
    打开该nb工具后的样子是这样的
    这里写图片描述
    没听过的的兄弟请点此处查阅后继续查看本文章

1. 发现问题

兄弟一看,情况不对呀,尽管分配了内存,但是内存还是会溢出
经过一下系列分析(分析详细过程):

 

okokok 接下来,就是见证奇迹的时刻,lets go
1. 这位兄弟告诉我,启动程序没问题,一访问就出问题,ok,(重点,要划线)
既然启动没问题,那你把启动的时候的内存分布情况与第一次访问的时候的内存情况发给我。
如下图片是第一次启动程序的情况

这里写图片描述
其实很多信息都很明了了,启动程序的分配的堆内存大小、程序所占用的堆内存大小,暂时看起来是没什么毛病,内存的大小并没有什么异常的情况,而且此时并没有发声内存溢出的异常。
 

但是,没有问题怎么会出异常呢,表开心的太找,下面这张图片是没有为程序启动的时候分配内存,并且发起了一次请求后的内存情况。
这里写图片描述

最大内存瞬间暴涨好几倍,而且程序同时抛出如下异常
这里写图片描述

嗯,问题出来

 

要解决的就是你,此时,问题bug已经重现,问题发现,第一关完美通关!!!

2. 分析问题

好的女王大人

前面说了这么多(扯。蛋。),但是,问题就是这么个问题,内存溢出,ok下面就是真正的展现技术的时刻了,你们给我坐正咯

内存出现溢出后,我让这位朋友分配了一下启动的最大内存与最小内存
这里写图片描述

既然问题已经出来了,那就用jvisualvm分析一下内存把,第一次请求出现的问题是内存暴涨,既然是内存问题,那么我们就对症下药,分析内存。
这里写图片描述

点击上图堆dump按钮进行堆内存分析,点击后如下所示
这里写图片描述

这里写图片描述

点击类后查看对象的内存占比情况如下,点击大小按钮进行内存占比大小排序

这里写图片描述

找到这个可恨的特务了,就是你,害的我兄弟被领导大问号脸,

3. 解决问题

继续跟踪这个对象,看丫的到底是个什么东西,有必要搞他一搞。

右击该对象,点击在实例视图中显示按钮,跳转如下页面

 

跟踪对象发现,名字竟然是一个叫做headerbuffer的东西,看名字,可能是一个request请求的header的缓冲区,占了400多m,一个request的请求头,你占了400多m,脸呢?

 

问题找到了,一个request的请求头占了四百兆,后续根据这个结果发现,为这个程序分配了两个g的最大内存之后,每次请求都会生成400m的该byte数组,接下来就定位到了请求的身上。

问题找到了,接下来就该看代码了,代码是这位兄弟写的,我就不方便随便贴人家的代码了,我先让这位兄弟检查一下代码,这个接口上做没做什么特殊处理,拦截器、过滤器、所有跟request请求相关的配置,都检查一遍,最后在springboot的配置文件中发现了如下配置:

这里写图片描述

这简直就是自己挖坑给自己跳呀,具体配置说明兄弟就不再解释了

 

 

满脑子黑人问号不再多bb了,咱们在这不多讨论该兄弟为什么这么写

jvisualvm、 jprofile真的是一个内存优化、排查问题的一个好工具,java们早晚会用到它,jprofile教程网上并不少,但是讲的好的并没有几个。重要的还是要自己去熟悉,去理解。

该篇文章仅作为内存溢出的一个解决思路

另提醒各位程序朋友们,可能做不到每一行代码都能刨根问底知道底层是怎么实现、什么原理,但是尽量知道你写或copy的每一行代码什么意思,影响有多大。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值