[JAVA]websocket引起的内存泄漏问题排查

这篇具有很好参考价值的文章主要介绍了[JAVA]websocket引起的内存泄漏问题排查。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

websocket引起的内存泄漏问题排查

1 问题描述

项目运行一天后出现了java.lang.OutOfMemoryError: GC overhead limit exceeded的错误,造成系统宕机。这说明给JVM分配的内存已经耗尽,不足以支撑垃圾回收进行内存回收工作,意味着程序占用的内存随着时间大小提升,最终耗尽。

2 问题分析与排查

2.1 宏观分析

从字面意思来看,GC(garbage collection)所需的内存不足,空闲内存与GC之间平衡的一个限制被打破,当经过几次GC之后,只有少于2%的内存被释放,也就是很少的空闲内存,可能会再次被快速填充,这样就会触发再一次的Full GC。如此往复,CPU大部分的时间在做GC操作(Full GC所需的时间很长),具体的业务操作也因为内存不足而无法运转,整个应用程序就崩溃了。虽然和C++不同的是,JAVA拥有独特的垃圾回收机制,程序员可以较少的担忧资源回收的问题,但是这种机制并不可能100%防止内存泄漏,一些难以察觉的代码实现或是配置都可能会造成这种机制失效,例如JAVA拥有多种不通强度的引用关系,例如强引用(strong reference),弱引用(weak reference),软引用(soft reference)和虚引用(phantom reference)。

引用类型 回收时间 生存时间
强引用 不回收 JVM停止
软引用 内存不足时 内存不足时
弱引用 GC运行时 GC运行后
虚引用 未知 未知

可以看到,JVM在设计中尽可能避免了内存溢出的问题,主要引用类型为软引用和强引用,在内存不足时,软引用将会被释放。

2.2 查看gc回收日志

首先先找到项目对应的pid,可以使用ps -ef | grep java获取,随后在启动项目的命令中添加以下参数

java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log demo.jar

其中,+printGCDetails+PrintGCDateStamps分别确保了输出gc细节和时间戳,这有助于我们发现问题,-Xloggc:gc.log则是指定了输出的日志文件名称。
websocket内存溢出,java,websocket,jvm
可以看到,每条信息的组成为时间戳+执行的操作+不同区的使用情况+回收所需时间,以上图中第一条日志为例,在2023-03-27T22:25:51发生了一次GC(System.gc())PSYoungGen区域在GC前使用了412645K,GC后的大小为61872K,该区域的总大小为1949696K,而对于Full GC,还会显示ParOldGen区域的信息。从日志中我们可以至少获得以下信息:

  • full gc所需的时间比一般gc更长(0.09秒对0.02秒)
  • full gc的频率非常高(1分钟一次,项目实际生产情况为1秒一次)
  • 出现了allocation failure(内存分配失败引起,JVM会执行Young GC回收年轻代的内存,如果完成后仍需内存回收,则会执行Full GC对年轻代和老年代进行回收)
  • 释放后的老年代大小正在缓慢增加(需观察更长时间的日志)

从上面信息中,可以推断出程序一定有设计不足的地方,显然出现了严重的内存泄漏,而之所以还没有崩溃,是因为不断触发Full GC释放出了足够的内存,对用户而言此时可能会感知到的只是略微卡顿和较慢的响应。而最后一点,老年代的大小随着时间正在逐渐变大,这无疑是一颗定时炸弹,可以预见的是,当老年代大小逐渐被耗尽,将会加速程序的崩溃。

2.3 寻找导致内存泄漏的根源

现在已经可以确定发生了内存泄漏,但是如何寻找导致内存泄漏的原因成为了下一个难题。好在已经有了较为成熟的工具帮助我们,它就是MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,但也可以单独使用,并且支持Linux,Mac,Windows系统。它的下载连接是链接: 官网。需要注意的是,最新版本需要JDK11支持,推荐下载1.7.0版本,只需要JDK8即可。
先利用jmap获取一个堆内存快照,jmap -dump:format=b,file=myjmapfile.hprof 进程id,随后用MAT打开即可查看堆内存占用情况。
websocket内存溢出,java,websocket,jvm
在dominator_tree中,可以发现名为WsFrameServer的类占据了绝大部分堆内存,继续展开,可以发现java.nio.HeapCharBufferjava.nio.HeapByteBuffer占据了绝大部分的内存。
websocket内存溢出,java,websocket,jvm
其实到这里,我们已经可以推断出问题了,那就是Buffer缓冲区太大,而它又发生在websocket当中,所以我们只需要找到websocket初始化缓冲区大小的地方,即可解答为什么缓冲区会如此之大的问题。

在Websocket配置类中,果然发现了问题所在
websocket内存溢出,java,websocket,jvm
此处将textBufferSizebianryBufferSize设置成了50MB,因此很容易导致内存不足以回收。

3 解决办法

3.1 临时办法-减小buffer size

textBufferSizebianryBufferSize设置相对较小,同时满足业务要求。然而,这种做法却并不能绝对保证内存溢出问题的解决,因为我们仍然没有确切的找到哪些对象因为哪些原因没有被回收导致的内存溢出。但这种做法应该能够延缓系统崩溃的时间。

3.2 更换Tomcat版本

也有人提到SpringBoot和Tomcat有一些微妙的关系,例如链接: link。文章来源地址https://www.toymoban.com/news/detail-544204.html

到了这里,关于[JAVA]websocket引起的内存泄漏问题排查的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用asan检测内存泄漏、堆栈溢出等问题

    操作过程参考:链接 缘起:程序在移动端崩溃,mac端复现不了,于是在写个崩溃位置函数的调用demo,使用ASAN工具进行排查。 验证过程 1、代码 main.cpp 使用附加ASAN工具的方式进行编译: 执行: 没有问题,以上是验证过程,如有问题执行时ASAN会提示有问题的相关位置。 介绍

    2024年02月11日
    浏览(61)
  • 使用Visual Leak Detector排查内存泄漏问题

    目录 1、VLD工具概述 2、下载、安装VLD 2.1、下载VLD 2.2、安装VLD 3、VLD安装目录及文件说明

    2024年02月07日
    浏览(43)
  • 如何逐步排查因文件问题导致的内存溢出

    逐步排查内存溢出问题通常需要一系列的步骤,其中逐渐增大传输文件的大小,并观察内存使用情况,是一种合理的方法。下面是您可以采取的步骤: 增大传输文件大小: 将传输的文件大小逐步增大,这样您可以模拟更大的资源负载。这有助于观察内存使用情况在不同负载

    2024年02月11日
    浏览(41)
  • Java内存溢出问题深入探究及其解决策略

    Java内存溢出是一个常见且棘手的问题,可能会导致程序的性能急剧下降或者崩溃,给业务带来严重的影响。为了深入解析和理解此问题,本文将详细探究Java的内存模型,内存溢出的根本原因,诊断方法以及解决策略。 1.1 Java内存模型 Java内存空间主要包括以下几个部分:方法

    2024年02月09日
    浏览(49)
  • 记1次生产环境java进程内存泄漏问题定位(使用Arthas)

    简介 | arthas, Alibaba 开源的 Java 诊断工具,参照文档安装使用很简单,在线下载或者离线下载后解压运行,启动arthas-boot.jar,会自动扫描jps进程,根据序号选择后进入arthas界面: 常用的是dashboard,thread命令,dashboard命令能扫面当前java进程的全局信息,包括堆栈和线程信息,

    2024年02月22日
    浏览(52)
  • NumPy使用不当引起的内存泄漏

    以下是一段会引起内存逐步累积的代码: 代码大意 :处理n个user的数据,将每个user的数据按照时间排序,取最早的10条的前三列保存 为了监控性能,我们使用python自带的分析工具tracemalloc跟踪内存分配,使用方法见: Python-tracemalloc-跟踪内存分配_Rnan-prince的博客-CSDN博客 运行

    2024年02月08日
    浏览(36)
  • Java应用堆外内存泄露问题排查

    最近有个java应用在做压力测试 压测环境配置: CentOS系统 4核CPU 8g内存 jdk1.6.0_25,jvm配置-server -Xms2048m -Xmx2048m 出现问题如下 执行300并发,压测持续1个小时后内存使用率从20%上升到100%,tps从1100多降低到600多。 首先使用top命令查看内存占用如下 然后查看java堆内存分布情况,查

    2024年02月12日
    浏览(37)
  • Android之内存泄漏与内存溢出

    内存泄漏(memory leak):是指程序在申请内存后,无法释放已申请的内存空间,导致系统无法及时回收内存并且分配给其他进程使用。通常少次数的内存无法及时回收并不会到程序造成什么影响,但是如果在内存本身就比较少获取多次导致内存无法正常回收时,就会导致内存

    2024年02月13日
    浏览(49)
  • 什么是内存溢出,什么是内存泄漏?

    提示:以下是本篇文章正文内容,下面案例可供参考 假设我们 JVM 中可用的内存空间只剩下 3M,但是我们要创建一个 5M 的对象,那么,新创建的对象就放不进去了。这个时候,我们就叫做内存溢出。就好比是一个容量只有 300ml 的水杯,我们硬要往里面倒500ml 的水,这时候,

    2024年02月12日
    浏览(42)
  • 性能优化-内存泄漏、内存溢出、cpu占用高、死锁、栈溢出详解

    含义:内层泄露是程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费。(换言之,GC回收不了这些不再被使用的对象,这些对象的生命周期太长) 危害:当应用程序长时间连续运行时,会导致严重的性能下降;OOM;偶尔会耗尽连接对象;可

    2024年01月19日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包