有一个服务经常会停止服务,一开始没特别注意,出问题就重新部署

后来有一次重启前看了眼 GC,发现一直在 Full GC:

[149644.445s][info][gc,start       ] GC(2210) Pause Full (Allocation Failure)
[149644.447s][info][gc,phases,start] GC(2210) Phase 1: Mark live objects
[149644.708s][info][gc,phases      ] GC(2210) Phase 1: Mark live objects 261.113ms
[149644.708s][info][gc,phases,start] GC(2210) Phase 2: Compute new object addresses
[149644.771s][info][gc,phases      ] GC(2210) Phase 2: Compute new object addresses 62.603ms
[149644.771s][info][gc,phases,start] GC(2210) Phase 3: Adjust pointers
[149644.903s][info][gc,phases      ] GC(2210) Phase 3: Adjust pointers 131.929ms
[149644.903s][info][gc,phases,start] GC(2210) Phase 4: Move objects
[149644.903s][info][gc,phases      ] GC(2210) Phase 4: Move objects 0.011ms
[149644.905s][info][gc,heap        ] GC(2210) DefNew: 314553K->314553K(314560K)
[149644.905s][info][gc,heap        ] GC(2210) Tenured: 699071K->699071K(699072K)
[149644.905s][info][gc,metaspace   ] GC(2210) Metaspace: 83387K->83387K(1126400K)
[149644.905s][info][gc             ] GC(2210) Pause Full (Allocation Failure) 989M->989M(989M) 459.957ms
[149644.905s][info][gc,cpu         ] GC(2210) User=0.46s Sys=0.00s Real=0.46s
[149644.907s][info][gc,start       ] GC(2211) Pause Full (Allocation Failure)
[149644.910s][info][gc,phases,start] GC(2211) Phase 1: Mark live objects
[149645.168s][info][gc,phases      ] GC(2211) Phase 1: Mark live objects 258.422ms
[149645.168s][info][gc,phases,start] GC(2211) Phase 2: Compute new object addresses
[149645.231s][info][gc,phases      ] GC(2211) Phase 2: Compute new object addresses 63.401ms
[149645.231s][info][gc,phases,start] GC(2211) Phase 3: Adjust pointers
[149645.365s][info][gc,phases      ] GC(2211) Phase 3: Adjust pointers 133.363ms
[149645.365s][info][gc,phases,start] GC(2211) Phase 4: Move objects
[149645.367s][info][gc,phases      ] GC(2211) Phase 4: Move objects 1.892ms
[149645.368s][info][gc,heap        ] GC(2211) DefNew: 314559K->312083K(314560K)
[149645.368s][info][gc,heap        ] GC(2211) Tenured: 699071K->699071K(699072K)
[149645.368s][info][gc,metaspace   ] GC(2211) Metaspace: 83387K->83387K(1126400K)
[149645.368s][info][gc             ] GC(2211) Pause Full (Allocation Failure) 989M->987M(989M) 460.962ms
[149645.368s][info][gc,cpu         ] GC(2211) User=0.46s Sys=0.00s Real=0.46s

服务限制了 4G 内存,在没有指定 -Xmx 的情况下只能使用 1G 内存,

了解更多 GC 内容看这里: HotSpot Virtual Machine Garbage Collection Tuning Guide 和 GC Tuning: In Practice

当时着急用服务就又直接重启了,直到今天,才在重启前尽可能保留了更多的信息。

下面是监控和 GC 的实时截图:

服务启动两天后,实际上在1天前就已经占满内存开始频繁 GC。

GC 实时信息:

FGC 比 YGC 还多,E年轻代满了,O老年代也满的。每次可用的只有 S1, S2 中的不到 10% 的空间。

这次本来要导出 dump 信息,可惜手快重启没拷出来。等新服务启动一段时间后,在线上通过 jps 查看 id,然后使用 jmap -dump:live,format=b,file=heap.bin <pid> 导出 dump 信息。

jmap 详细资料: https://docs.oracle.com/en/java/javase/11/tools/jmap.html#GUID-D2340719-82BA-4077-B0F3-2803269B7F41

导出 heap.bin 后,先通过 VisualVM 打开了,能看到有限的信息,关键还不熟悉 OQL 语法,很不方便,因此使用 内存分析器(MAT) 进行分析。

Memory Analyzer (MAT) 内存分析器(MAT)
Eclipse Memory Analyzer 是一个快速且功能丰富的 Java 堆分析器,它可以帮助您发现内存泄漏并减少内存消耗。
使用内存分析器分析数亿个对象的高效堆转储,快速计算对象的保留大小,查看是谁阻止垃圾收集器收集对象,运行报告自动提取泄漏嫌疑人。

用 mat 打开后,根据提示信息找到了下面的地方:

XDocReportRegistry 中的 MapCacheStoreage 占用了 63.81% 的空间,从名字来看是缓存,而缓存是最容易出现内存溢出的地方。

在工具类中有如下调用:

这里的 loadReport 如下:

这个方法默认是缓存的,但是使用的地方每次都是传入新的 InputStream,缓存的 IXDocReport 根本没有用上,因此该方法只要执行一次都会导致缓存增加一个,最终会将内存占满。

最简单的解决方法就是调用 loadReport 的时候指定 cacheReport=false 禁用缓存。

解决了这里内存溢出的问题后,服务所用内存应该会大幅度降低,等服务运行一两天后再补充两张资源占用图。

在 2019 年博客总结 中提过:

因为我发现很多技术博客的内容中,很少涉及相关内容的出处,如果我只了解了别人博客提到的,关注的内容,看不到全貌,我自己总感觉不够,我想看到更详尽的资料,即使用到的只是其中一部分,但是提供出处就可以让人有了解更多的机会,对你博客内容的可信度提高很多。因此 2020 年会多一些轮子似的博客,但是会提供详细的出处和扩展资料。

所以,本文中提供的所有链接的价值要远远大于本文。如果有兴趣,一定要看!

记一次内存溢出排查过程相关推荐

  1. 转:记一次linux oom内存溢出排查过程

    @转:记一次linux oom内存溢出排查过程 记一次linux oom内存溢出排查过程 2018年08月16日 14:13:49 enchanterblue 阅读数 4099更多 分类专栏: --- ...

  2. 记一次linux oom内存溢出排查过程

    一,背景 收到应用服务报警,然后登录上服务器查看原因,发现进程不再了. 二,问题分析 1,那么判断进程被干掉的原因如下: (1),机器重启了 通过uptime看机器并未重启 (2),程序有bug自动退 ...

  3. 记一次SOFA内存泄漏排查过程

    记一次内存泄漏排查过程 起因 某天中午大家还在安静的午休,睡得正香的时候突然被一阵手机滴-滴滴直响短信惊醒.一看是应用的服务器告警并且对应服务的所有机器都在告警"健康检查失败,自动拉下线&q ...

  4. golang 记一次data race排查过程

    golang 记一次data race排查过程 背景 data race 现场 解决思路 经验总结 data race在写并发代码时候经常遇到,相关基础概念的介绍可以参考之前一篇文章:golang d ...

  5. 【Java内存溢出排查】gc监测以及内存突增问题排查

    前情提要 文档:[Java内存溢出排查]测试环境服务器挂... 链接:http://note.youdao.com/noteshare?id=783e7ec89950f4167867ef3ef3347 ...

  6. linux 内存溢出排查_记一次JAVA 线上故障排查完整套路

    JAVA线上故障排查全套路 线上故障主要会包括cpu.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍.同时例如jstack.jmap等工具也 ...

  7. openjdk platform binary 内存_记一次内存溢出导致的生产事故

    背景 因为同事的离职,半路被迫接手的一个可视化项目,使用ElasticSearch作为OLAP数据库.Docker作为部署工具等,突然有一天项目现场环境出现JVM内存溢出问题,被迫披挂上阵定位问题的原 ...

  8. linux 内存溢出排查_【开发者成长】JAVA 线上故障排查完整套路!

    云栖号资讯:[点击查看更多行业资讯] 在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! 线上故障主要会包括 CPU.磁盘.内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以 ...

  9. linux 内存溢出排查_linux下valgrind内存问题排查

    c/c++的内存管理一直都是程序猿最头痛的事情,内存越界.数组越界.内存泄漏.内存溢出.野指针.空指针..., 随便一个问题都可能让程序崩溃.而且往往问题的源头都比较隐蔽,让人很难排查出问题的根源所在 ...

  10. JVM频繁GC内存溢出排查

    文章目录 前言 例子程序 查看堆中对象分配信息 jmap -histo(推荐) jmap -dump + Java VisualVM 内存溢出时自动生成堆转储文件(推荐) Java VisualVM ...

最新文章

  1. python拟合求参_机器学习作业(四)神经网络参数的拟合——Python(numpy)实现
  2. HashMap集合遍历的五种方式
  3. Python 绘图与可视化 matplotlib 制作Gif动图
  4. 现代密码学1.3--古典密码/historical cipher
  5. 通信 / DHCP 四次握手
  6. shell判断false_Linux脚本shell常用判断式
  7. IDEA中新建项目Static Web 中没有vue.js
  8. latex表格名的引用问题
  9. lru调度算法例题_嵌入式必会!C语言最常用的贪心算法就这么被攻略了
  10. [转]项目方面的做人处事
  11. 常用Linux 服务器命令--各种性能指标命令
  12. oracle入门操作3(关于查询 )
  13. 搭建内网穿透工具-ngrok
  14. java.security.cert.CertificateException: X.509 not found,X.509证书找不到
  15. 【2010强悍教程】一次性永远激活7290自带浏览器上网和彩信收发功能,不能上网的进。...
  16. 太恐怖!黑客能把你的耳机变成麦克风用来监听
  17. 如何关闭系统自带的屏幕放大125%
  18. CorelDRAW 发光字想制作的漂亮一些就得会这些技巧
  19. FCK编辑器在项目中的引入
  20. 猿创征文|深入剖析多态的实现原理与虚函数指针

热门文章

  1. ML 训练与测试数据不满足同分布 - 如何检测?如何解决?
  2. 密码技术挑战赛-多选题
  3. 基于Matlab的粒子群算法在分布式能源调度优化问题中的应用
  4. 解决困扰很久的pycharm不能加断点问题
  5. Codeforces 1379 C Choosing flowers
  6. VC6.0打开老工程一片空白
  7. HUAWEI华为笔记本MateBook E 2023款(DRR-W76)原厂Win11系统工厂模式(含智能还原)
  8. Android中关于字符串与颜色的转换问题
  9. 《算法图解》学习笔记(一):二分查找(附代码)
  10. 游戏公司如何监控设备?手把手教你实操