内存飚高排查(二)

一、问题描述

研发反馈EDI应用请求无响应。

二、排查路径

1)查看日志

日志中发现异常信息:java.lang.OutOfMemoryError: GC overhead limit exceeded

2)查看GC

1
2
3
4
5
6
7
$ jstat -gc 9459
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
1863680.0 1863680.0 0.0 0.0 1864704.0 1864704.0 11185152.0 11185145.3 74112.0 71884.7 9344.0 8819.3 82 7.997 3574 1139.764 1147.761
1863680.0 1863680.0 0.0 0.0 1864704.0 1864704.0 11185152.0 11185152.0 74112.0 71884.7 9344.0 8819.3 82 7.997 3944 1219.075 1227.072
1863680.0 1863680.0 0.0 0.0 1864704.0 1864704.0 11185152.0 11185145.1 74112.0 71884.7 9344.0 8819.3 82 7.997 3945 1219.501 1227.498
1863680.0 1863680.0 0.0 0.0 1864704.0 1864704.0 11185152.0 11185145.1 74112.0 71884.7 9344.0 8819.3 82 7.997 3945 1219.501 1227.498
1863680.0 1863680.0 0.0 0.0 1864704.0 1864702.6 11185152.0 11185145.0 74112.0 71884.7 9344.0 8819.3 82 7.997 3947 1219.709 1227.705

3)Dump内存

jmap -dump:live,format=b,file=heap.dump [pid]

三、分析Dump文件

1)根据Leak Suspects分析

image-20211113110401494

image-20211113104506412

由以上图可以看出是AsyncLogImpl占用较高。

image-20211113104724014

由以上可推出是AsyncLogImpl中的阻塞队列导致的内存溢出。

2)根据类实例直方图分析

image-20211113110545594

image-20211113110852340

从类直方图中可观察出是应用的类com.jd.edi.utils.log.impl.AsyncLogImpl$LogEntry中有大量String对象导致的内存过高。然后查看该类的实例数为37,764,Top15都在1MB以上。

image-20211113110923075

此时,通过GCRoot链(下图)可以分析出来是由于com.jd.edi.utils.log.impl.AsyncLogImpl的阻塞队列过长导致。

image-20211113112051014

image-20211113112209784

四、修改代码

1)修改AsyncLogImpl中阻塞队列大小,且支持配置。

2)增加消费线程数量,且支持配置。

评论