如题,线上有个服务跑着跑着就会 OOM ,导致所有请求失败,内存无法回收。
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to /xxx/xxx/bootstrap/java_pid39726.hprof ...
用 VisualVM 分析 dump 文件发现,有个大对象占用了 33%的内存,如图①,查看该对象,发现里面大概有 200w 个对象,有一部分是空的,最大的几个对象就是顶部的那四五个。这些对象是一个 JSON 字符串,最上面几个大对象排查发现其中的 url 部分有大量重复,可能是前端提交数据或者后端处理 url 拼接的时候循环有问题,导致有大量重复的 url 使得其中这个对象特别的大。排查数据库,length 这个字段,最大的几个分别占用 9469799 ,4764368 ,4725799 ,4571257 。
JVM 调优经验较少,不知道是不是这么个排查流程,也不知道排查的点对不对。希望有经验的大佬给点指导。 补充几点:
1
jiobanma OP 大佬们可以给点指导建议,感谢。
|
2
xiangxiangxiang 2022-07-23 10:29:37 +08:00
代码上传到 github 让大伙帮忙看看 🐶
|
3
xiangxiangxiang 2022-07-23 10:31:53 +08:00 1
盲猜这个大对象是不是一个多层嵌套 map 或者说是树型结构(类似于文件目录+文件或者一颗特别大的类目树带类目下的商品详情这种场景),然后代码里有的地方不合理的 toJSON 打印日志,导致 oom 了?
|
4
chendy 2022-07-23 10:33:38 +08:00
用 eclipse mat 分析一下试试?
找内存占用大的线程,看看里面在执行什么逻辑 |
5
jiobanma OP @xiangxiangxiang 哈哈哈 上传 github 怕不是要和凡凡做室友了(dog 。 这个大对象是一些业务数据,之前的老代码把很多业务数据拼装成了一个 json 字段存到了数据库里。 有异常的几个对象的 json 里面充斥着大量重复的 url(应该是前端或者后端循环拼接 url 的时候死循环了)。 我只是不知道自己现在的排查方式对不对,是不是应该从这个角度分析。
@chendy mac 装 mat 有点不太好装,jprofile 我有点不太会用。 |
6
tonymua 2022-07-23 11:10:58 +08:00
我们之前 Prometheus 监控项的时候 tag 对应的 List 里面元素顺序不一样 有过类似的情况
|
8
micean 2022-07-23 11:19:08 +08:00
一般先考虑有没有文件处理业务,那种加载 excel 、csv 之类的
|
9
manecocomph 2022-07-23 11:28:27 +08:00
如果你觉得现在占 30%多的对象不够找出内存泄漏的真正源头, 我们一般把 heap 增大, 然后让它继续泄漏. 当你给它 8G heap 的时候, 还是 OOM, 还是占满, 然后去对比查看内存里的大对象, 就很快找到泄漏点了.
|
10
manecocomph 2022-07-23 11:34:33 +08:00
另外你标出来的 char[], byte[] 都很难找出来, 几乎所有的正常 Java 对象, 占大头的都是 char[], byte[] 等. 重点关注业务对象.
|
11
jiobanma OP @manecocomph 我们的这个 char[] byte[]就是业务的大 json 字段,这里面全是这个 json
|
13
manecocomph 2022-07-23 11:49:51 +08:00
@jiobanma 同意, 绝大部分 Java 应用里面占 heap 的都是 char[], byte[]. 这些 json 被那些业务对象引用, 查查那些业务对象多不多. 推荐暂时增加 heap 让他尽情泄漏, 找出泄漏源.
|
14
luozic 2022-07-23 12:00:37 +08:00
https://www.jianshu.com/p/9baea772cb21 随便搜搜 ,这个介绍挺详细的
|
15
dqzcwxb 2022-07-23 12:44:58 +08:00
前几天处理过差不多的问题,用 caffeine 做本机缓存解决了当然前提是数据更新频率低以及能够接受一定延迟
|
16
RuralHunter 2022-07-23 20:46:01 +08:00
找你们自己域名内的类,看看内存和数量不正常的。基础库的类一般看不出什么花头。
|
17
goldenAndGreen 2022-07-23 23:47:53 +08:00
没配垃圾回收器吗,oom 之前有垃圾回收监测吗?可以确定是哪个区域吗?
如果是 G1 和 ZGC 可能更麻烦... |
18
Nnq 2022-07-25 00:22:17 +08:00
你这个单纯拿出来一个截图很难说明问题, 分析 oom 也不是一下就能准确定位的
首先看看你所谓的占内存比较大的个体,看看为什么没有释放,是业务需求还是技术层面太多的字符串拼接之类的 还有在打日志的时候,是否也有拼接现象 ? 从这些方面看一看 |
19
xuyang2 2022-07-25 09:22:19 +08:00
找找是不是有循环体里面 string += 的操作?
|
20
jiobanma OP @xuyang2
@Nnq @goldenAndGreen @RuralHunter @dqzcwxb @luozic @manecocomph 已解决,MAT 分析爆出的那个异常接口,controller 没有做参数校验,导致 sql 查了全表的数据,本来只是查一条数据的,把内存压满了,但是 sql 还没执行结束,导致一直 gc ,但是没法释放空间。 |
22
luozic 2022-07-25 12:10:34 +08:00
定期扫 db 打性能分析日志,做优化。
|
23
zhangyaxiao072 2022-07-25 13:55:11 +08:00
可能是哪里的代码又问题;下次溢出可以多抓几次线程,jstack ,仔细看看里面的信息
|
25
jiobanma OP |
26
NeoZephyr 2022-07-26 10:10:30 +08:00
@manecocomph 继续泄露看到的也是 char[] bytes[] 大头啊
|