JVM堆内存泄露分析

news2025/7/15 22:50:54

一、背景

公司有一个中间的系统A可以对接多个后端业务系统B,一个业务系统以一个Namespace代表, Namespace中包含多个FrameChannel(用holder保存),表示A连接到业务系统B各服务实例的连接;A与B通过GRPC通信。

二、现象

测试使用一台服务实例A,对应后端的一个业务系统B,该业务系统有两台服务实例,正常情况NameSpace中包含两个FrameChannel

当后端业务系统升级上线重启时,会重新创建FrameChannel,但旧的FrameChannel在GC(自己创建大量client,发送埋点消息,并使用jstat观察gc数量,过程不详述了)时却没有被释放,正常情况下,FrameChannel数量为2,当B的两台服务器重启后,FrameChannel的数量变成4,并在gc时,没有被释放。

正常情况Framechannel有2个,即两条线,当重启B时,会变成4条线,查看堆内存FrameChannel对象,也是4个

既然仍能监控旧的FrameChannel,于是想到将旧的FrameChannel注销监控

再重新将A部署测试,发现当重启pp时,另外两个FrameChannel确实没有数据了,但堆内存中却仍然有4个FrameChannel对象(原因分析见下面的分析部分)

最后分析堆内存后,发现注销指标时少注销了一部分,重新开发,编译,打包,部署,并测试

发现FrameChannel对象仍然为4个,再分析堆内存,发现被Session引用,于是关闭所有client,再观察一会,FrameChannel数量终于变成了2个

三、分析

dump内存对象,并使用MAT分析, 查看哪些对象在使用FrameChannel

可以看见,一共4个FrameChannel对象,经过查看引用,发现3、4对象被Namespace中Holder引用,说明3、4是正常的连接;1、2没有被Hoder引用,是已经关闭的连接。选择第1个对象,查看谁引用它

共有3个对象引用它,

  1. 第一个this$0是FrameChannel的内部类DownstreamObserver,此内部类对象被grpc使用,经过代码分析,入口是FrameChannelStub,而此类只被Framechannel本身使用。
  2. 第二个arg$1是一个Lambda表达式生成的对象,此对象又被3个对象引用

查看这3个对象,再结果FrameChannel中设置指标监控的代码,可以知道是监控channelRoom所使用的Lambda表达式

进入guage方法

gauges即是上面第2个引用Lambda表达式的对象

再查看registry.register方法

metrics即是上面第1个引用Lambda表达式的对象

进入OnMetricAdded, 往下点几层,可看见

可见将gauge包装成JmxGuage,通过JMX暴露出来.

归纳一下,这三个引用对象所在的类分别是

  • 公司自己封装的Metrics指标类
  • com.codahale.metrics.MetricRegistry
  • com.codahale.metrics.jmx.JmxReporter

看一下,这三个类实例是什么时候被创建的

  • Metrics 是在最开始就会被创建

  • com.codahale.metrics.MetricRegistry和 com.codahale.metrics.jmx.JmxReporter 在 MetricsFactory 类被加载的时候就会被创建

MetricsFactory是一个监控指标的工具类,可以说是全局的,不会被JVM卸载,导致其引用的对象不会被释放。

  1. 引用FrameChannel的第三个对象是Session中的channels

channels是一个Map类型,其作用是存储namespace对应的frameChannel,在session第一次向后端业务系统发起事件时,会从Namespace中的Holder选择一个FrameChannel,放入自身channel的Map中缓存起来,下一次使用时直接从channels map中查询,不用从namespace holder中获取。

一个 session 对象代表一个客户端到长连接网关的连接,其是在客户端连接长连接网关时被创建的。

而session被3个对象引用,下面标的是4个,因为SessionRoom同时会被Namespace中的rooms和FrameChannel中的channelRooms引用

我们先看下SessionRoom,它会不会不被释放?

不会,因为NamespaceManager会定时(每30s)检查Namespace和FrameChannel中的SessionRoom是否为空,如果为空,则将其从rooms和channelRooms Map中删除,JVM就可以回收SessionRoom。

再看下SessionPool, 它会不会不释放Session?

不会,因为SessionPool也会定时检查已经关闭的Session,并将其删除

再看下ClientHead, 它会不会不被释放?

不会,ClientHead是Netty-SocketIO框架创建的对象,当客户端连接长连接网关时,会创建ClientHead对象,放入到ClientBox中,当连接关闭时,会将其中ClientBox中删除,具体请见类:com.corundumstudio.socketio.handler.ClientsBox

经过以上分析,发现使用 MetricsFactory 创建出的Metrics,在使用gauga等包含Lambda表达式的方法时,会使被引用的对象无法被GC回收,从而造成内存泄露。

四、总结

使用全局的对象时,最好不要直接引用生命周期变化的对象,如果非要引用其它对象,则保证被引用的对象也是全局的,不会被销毁重建,如果被引用对象会被销毁重建,则在销毁时,从全局对象中删除对其的引用,以免造成内存泄露。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/17692.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

立创EDA仿真入门2 实战全桥整流

立创EDA仿真入门2 实战全桥整流一、全桥整流原理二、操作步骤1. 在立创EDA新建仿真项目和原理图2. 绘制原理图电阻的作用函数发生器的设置3. 点仿真4. 使用电容代替电阻5. 加上负载一、全桥整流原理 全桥整流也称整流桥堆,使用4个或更多相同的二极管组成整流电路&am…

四、MySQL 提权方式

1 UDF 提权 secure_file_priv 是用来限制 load dumpfile、into outfile、load_file() 函数在哪个目录下拥有上传或者读取文件的权限 show global variables like secure%; 修改 my.cnf 文件,在 [mysqld] 块下,如果没有 secure_file_priv 则新增 指定目录:secure_file_pri…

[附源码]java毕业设计商城管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Oracle 11g安装使用、备份恢复并与SpringBoot集成

背景 最近接手了一个祖传项目,一个十几年前的 .Net 客户端项目,近期需要修改一个小功能,项目用到了 Oracle 数据库,以下是我在 Windows 7 旗舰版虚拟机上安装使用 Oracle 11g 的记录。 在 Windows 7 虚拟机上安装了 Oracle 服务…

招聘小程序开发功能点_分享招聘小程序的优势

招聘小程序的主要用户就是企业招聘端和找工作人员的用户端,下面从这两个端来对招聘小程序开发的功能进行介绍。 企业端功能 1、岗位发布:企业根据自身岗位需求,在招聘app上发布招聘岗位及所需技能。 2.简历筛选:根据求职者提交的简历选择合适的简历,并对公开发布的简历进行筛…

利用numpy库定义一个等比数列:logspace()函数

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 创建等比数列 logspace()函数 选择题 关于以下代码下列说法错误的是? import numpy as np print("【执行】np.logspace(1,3,3,base2)") print(np.logspace(1,3,3,base2)) print…

物联网智能家居系统概述和相关技术

物联网的发展和形成方方面面涉及了很多相关的技术。随着物联网的逐渐成熟,物联网的分层体系也趋于统一,现阶段普遍接受一种三层结构的物联网,即由下至上依次为:感知层、网络层、应用层。 图1-1 物联网体系结构图 所以&#xff0c…

JAVA SpringMVC老项目集成knife4j

需求: 原有一直使用showdoc工具对内或对外进行接口文档和功能的沟通,上层领导觉得人工进行手写 浪费很多人工维护时间可能会做到接口更改而面对静态文档而更新不及时showdoc的劣势是不能进行在线调试 需要辅助其他调试工具但领导只需要类似swagger官方的页面即可。通…

开发前后端交互规范与请求封装

开发前后端交互规范与请求封装一,背景说明二,Axios请求封装三,数据对象封装1,前端封装2,后端封装四,总结五,Axios拦截器七,Restful请求1,Restful的由来2,Rest…

亲测好用的开发工具【1】 RuoYi-MT

亲测好用的开发工具【1】 文章目录亲测好用的开发工具【1】RuoYi-MT1 问题引入2 RuoYi-MT3 使用RuiYi-MTRuoYi-MT 1 问题引入 没错,又是若依,今天遇到一个需求,就是用若依打底,做一个自己的前后端分离的后台管理系统。 但是吧&…

电科大离散数学-1-集合论基础

目录 1.1 集合的初见 1.1.1 集合的定义 1.1.2 集合的表示方法 1.1.3 集合的基数 1.2 特殊集合与集合间关系 1.2.1 空集 1.2.2 全集 1.2.3 集合的相等关系 1.2.4 包含关系 1.2.5 幂集 1.3 集合的运算 1.3.1 并运算 1.3.2 交运算 1.3.3 补运算 1.3.4 差运算 1.3.…

使用VUE3.0版本搭建H5模板

使用VUE3.0版本搭建H5模板 仓库地址,有需要的可以参考参考 https://gitee.com/young_frivolous/vue3-app-template/tree/master为了方便每次写项目都要去搭建一个框架,今天使用vue3.0从0开始实行一个开箱即用移动端模板,基于vue3.0全家桶 v…

Windows安装和完全卸载MySQL8(以MySQL8.0.31版本为例) 之 Zip 方式(超详细教程)

文章目录一. 前言二. 安装1.下载MySQL2. 安装MySQL3.小结:4.修改环境变量3.完全卸载一. 前言 MySQL8相比之前版本改动还是挺大,主要有以下几点: MySQL8之后并不需要my.ini,会自动的生成data文件夹在解压之后的文件,端…

ArcGIS水文分析工具

Fill 填洼 凹陷点是指未定义流域方向的像元;其周围的像元均高于它。倾泻点是汇流区域中具有最低高程的边界像元。如果凹陷点中充满了水,则水将从该点倾泻出去。Arcpy代码: Fill(in_surface_raster, {z_limit})Flow accumulation 流量 通过流…

某邮储银行数据归集系统在HTAP场景下的选型与实践

导语:面对HTAP能力的需求与云原生时代的趋势,以及国产化的浪潮,某邮储银行携手OceanBase打造了云原生时代下的国产分布式数据库场景实践体验。以下内容整理自某邮储银行运维方DBA的自述。 业务痛点 我们有一套针对业务内部的运营数据归集系统…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.12 ES 简介

SpringBoot 【黑马程序员SpringBoot2全套视频教程,springboot零基础到项目实战(spring boot2完整版)】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.12 ES 简介4.12.1 介绍4.12.2 全文搜索工作原理4.…

C++学习笔记(Ⅳ):C++提高编程

1 模板 1.1 模板的概念 建立通用的模板&#xff0c;提高代码复用性 1.2 函数模板 c还有一种利用模板的泛型编程 1. 语法 建立函数&#xff0c;其返回值类型和形参类型用虚拟类型代表 template<typename T> // 函数模板 template<typename T> // 声明一…

使用token登录提交到github

首先从GitHub上clone自己的仓库 git clone https://github.com/ljx2/SunnyWeather.git 修改一些文件 然后 git add ./ git commit -m ‘first commit’ 然后 git push origin main 提示输入用户名密码来验证 输完之后又提示需要创建token来上传&#xff0c;由于安全&#x…

M41T62Q6F 一款具有报警功能的低功耗串行实时时钟(RTC)芯片

M41T62Q6F是一款带有 32.768 kHz 振荡器的低功耗串行实时时钟(RTC)。8 个寄存器用于提供 时钟/日历功能&#xff0c;配置为二进制编码的十进制&#xff08;BCD&#xff09;格式。另有 8 个寄存器提供报警&#xff08;闹 铃&#xff09;、32 KHz 输出、校准以及看门狗功能的状态…

《树莓派项目实战》第七节 使用声音传感器检测声音

目录 7.1 引脚介绍 7.2 工作原理 7.3 连接到树莓派 7.4 编写代码检测声音有无 在本节&#xff0c;我们将学习如何使用声音传感器检测声音&#xff0c;该项目设计到的材料有&#xff1a; 树莓派 * 1面包板 * 1杜邦线若干声音传感器 * 17.1 引脚介绍 声音传感器一共有3个引脚…