ThreadLocal内存泄漏问题

引子:

内存泄漏:是指本应该被GC回收的无用对象没有被回收,导致内存空间的浪费,当内存泄露严重时会导致内存溢出。Java内存泄露的根本原因是:长生命周期的对象持有短生命周期对象的引用,尽管短生命周期对象已经不再需要,但是因为长生命周期对象持有它的引用而导致不能被GC回收。

内存溢出:就是我们常说的OOM(OutOfMemoryError)异常,简单理解就是内存不够了,通常发生在程序申请的内存超出了JVM中可用内存的大小,就会抛出OOM异常。在JVM内存区域中,除了程序计数器外其他的内存区域都有可能抛出OOM异常。

ThreadLocal很好地解决了线程之间需要数据隔离的问题,同时也引入了另一个问题,在应用程序中通常会使用线程池来管理线程,那么线程的生命周期与应用程序的生命周期基本保持一致,如果线程的数量很多,随着程序的运行,时间的推移,ThreadLocal类型的变量会越来越多,将会占用非常大的内存空间,从而产生内存泄漏,如果这些对象一直不被释放的话,可能会导致内存溢出。

 

大家先看一下内存图:

 

从图中可以看出,ThreadLocal对象存在于堆中,有栈中的强引用指向它,也有ThreadLocalMap中的entry的弱引用键指向他。

“弱引⽤:只要垃圾回收机制⼀运⾏,不管JVM的内存空间是否充⾜,都会回收该对象占⽤的内存。”

而随着程序的运行,栈中ThreadLocal的强引用会消亡,只剩下弱引用连接着ThreadLocal独享,由于ThreadLocalMap.Entity中的key是弱引用,所以堆中的ThreadLocal对象会被回收(只要发生GC,弱引用对象就会被回收),但是ThreadLocalMap⽣命周期和Thread是⼀样的,它这时候如果不被回收,就会出现这种情况:ThreadLocalMap的key没了,value还在,这就会造成了内存泄漏问题(由弱引用引起的内存泄漏)。

而对于线程来说,线程的生命周期与应用程序的生命周期基本保持一致,所以一直会存在:Current Thread Refefence -> Thread -> ThreaLocalMap -> Entry -> value -> Object的强引用,这样value所强引用的Object对象迟迟得不到回收,就会导致内存泄漏。

如何解决弱引用导致的内存泄露问题?

ThreadLocalMap的设计中已经考虑到这种情况,所以ThreadLocal的get()、set()、remove()的时候都会清除线程ThreadLocalMap里所有key为null的value。

一旦将value设置为null之后,就斩断了引用与真实内存之间的强引用,就能够真正的释放空间,防止内存泄漏。

但是这只是一种被动的方式,如果这些方法都没有被调用怎么办?那你就每次使用完ThreadLocal变量之后,执行remove方法。

总结:ThreadLocalMap中的弱引用以及调用ThreadLocal各种方法后的清理只是增加了一层防护手段,还是有可能会导致内存泄露,真正想防止内存泄漏,需要编码的规范,使用完ThreadLocal后,及时调用remove()方法释放内存空间。

 

那为什么还要维持一个弱引用呢?

设置ThreadLocal对象的弱引用,这样做的目的是确保ThreadLocal对象在没有其他强引用时可以被垃圾回收。

key设计成弱引⽤同样是为了防⽌内存泄漏(这是另一个原因引起的内存泄漏)。假如key被设计成强引⽤,如果ThreadLocal Reference被销毁,此时它指向ThreadLoca的强引⽤就没有了,但是此时key还强引⽤指向ThreadLoca,就会导致ThreadLocal不能被回收,这时候就发⽣了内存泄漏的问题。

两个内存泄漏问题是不一样的

  • 这里是ThreadLocal变量无法被回收,导致内存泄漏;

  • 而弱引用导致的则是Value指向的object无法被回收,导致内存泄漏;

总结

首先,如果让key使用强引用指向ThreadLocal,则ThreadLocal对象无法被回收,导致内存泄漏;为了解决这个问题,让key使用弱引用指向Threadlocal,而这也会导致了Value无法被回收,造成内存泄漏,如何解决呢?我们在使用完ThreadLocal对象后,及时使用remove方法释放内存空间即可。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ABAP 定义复杂的数据结构

最近有个需求是实现ABAP数据类型与JASON类型的转换。想要创建个ABAP的数据类型来接JASON类型是个挺麻烦的事。例如下面这个JASON数据,是个很简单的数据结构。但对ABAP来说有4层了,就有点复杂了。 不过ABAP的数据类型也是支持直接定义数据结构的嵌套的。如…

LLM生成式 AI 项目生命周期Generative AI project lifecycle

在本课程的其余部分中,您将学习开发和部署LLM驱动应用所需的技巧。在这个视频中,您将了解一个能帮助您完成此工作的生成式AI项目生命周期。此框架列出了从构思到启动项目所需的任务。到课程结束时,您应该对您需要做的重要决策、可能遇到的困难…

dockerfile编写LNMP

目录 1. 项目环境 2. 服务器环境 二、部署nginx(容器IP为192.168.158.26) 1、整个Dockerfile文件内容 ​编辑 2、配置nginx.conf文件 3、构建镜像 三、部署mysql 1、整个Docker文件内容 3、生成镜像 4、启动镜像容器 5、验证mysql 四、PHP部署 1…

机器学习|决策树:数学原理及代码解析

机器学习|决策树:数学原理及代码解析 决策树是一种常用的监督学习算法,适用于解决分类和回归问题。在本文中,我们将深入探讨决策树的数学原理,并提供 Python 示例代码帮助读者更好地理解和实现该算法。 决策树数学原…

Go语言里面的各种疑难杂症

什么是闭包?闭包有什么缺陷? func AddUpper() func(int)int{var n int 10return func (x int) int{n nxreturn n} }func main(){f : AddUpper()fmt.Println(f(1))//11fmt.Println(f(2))//13fmt.Println(f(3))//16 }(1) AddUpper…

PyTorch学习笔记(十六)——利用GPU训练

一、方式一 网络模型、损失函数、数据(包括输入、标注) 找到以上三种变量,调用它们的.cuda(),再返回即可 if torch.cuda.is_available():mynn mynn.cuda() if torch.cuda.is_available():loss_function loss_function.cuda(…

【操作系统】虚拟内存相关分段分页页面置换算法

虚拟内存是什么? 【进程地址空间虚拟地址空间C/C程序地址空间就是那个4G的空间】 虚拟内存是操作系统内核为了对进程地址空间进行管理,而设计的一个逻辑意义上的内存空间概念。在程序运行过程中,虚拟内存中需要被访问的部分会被映射到物理内…

安防视频监控平台EasyCVR视频集中存储平台接入RTSP设备出现离线情况的问题解决方案

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

用户新增预测——baseline学习笔记

一、赛题理解 1. 赛题名称 用户新增预测挑战赛 2. 赛题数据集 赛题数据由约62万条训练集、20万条测试集数据组成,共包含13个字段。其中uuid为样本唯一标识,eid为访问行为ID,udmap为行为属性,其中的key1到key9表示不同的行为属性…

什么是RNN(循环神经网络)

什么是RNN(循环神经网络) 循环神经网络(Recurrent Neural Network),在识别图像时,输入的每张图片都是孤立的,认出这张图片是苹果,并不会对认出下一张图片是梨造成影响。 但对语言来说,顺序是十分重要的,“…

07 mysql5.6.x docker 启动, 无 config 目录导致客户端连接认证需要 10s

前言 呵呵 最近再一次 环境部署的过程中碰到了这样的一个问题 我基于 docker 启动了一个 mysql 服务, 然后 挂载出了 数据目录 和 配置目录, 没有手动复制配置目录出来, 所以配置目录是空的 然后 我基于 docker 启动了一个 nacos, 配置数据库设置为上面的这个 mysql 然后 启…

ARM汇编【1】:数据类型

与高级语言类似,ARM支持对不同数据类型的操作。我们可以加载或存储的数据类型可以是有符号和无符号字、半字或字节。这些数据类型的扩展名是:-h或-sh表示半字,-b或-sb表示字节,不表示字的扩展名。有符号数据类型或无符号数据类型之…

Consistency Models终结扩散模型

最近看到一篇论文,觉得特别有意思,并且在学术界引起了不小的动静,他就是一致性模型,据说图像生成效果快、质量高,并且还可以实现零样本图像编辑,即不进行一些视觉任务训练,可以实现图像超分、修…

基于springboot+vue的论坛系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…

改进YOLO系列:3.添加SOCA注意力机制

添加SOCA注意力机制 1. SOCA注意力机制论文2. SOCA注意力机制原理3. SOCA注意力机制的配置3.1common.py配置3.2yolo.py配置3.3yaml文件配置1. SOCA注意力机制论文 暂未找到 2. SOCA注意力机制原理 3. SOCA注意力机制的配置 3.1common.py配置 ./models/common.p…

Docker+Jmeter+InfluxDB+Grafana 搭建性能监控平台

当今互联网发展迅速,应用程序的性能监控显得越来越重要。 DockerJmeterInfluxDBGrafana 是一种常用的性能监控平台,可以帮助开发者快速搭建一套可靠的监控体系。在本文中,我们将介绍如何使用这些工具搭建性能监控平台,以便开发人…

实现chatGPT 聊天样式

效果图 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Chat Example</title&g…

第9步---MySQL的索引和存储引擎

第9步---MySQL的索引和存储引擎 1.索引 1.1分类 索引可以快速的找出具有特定值的行。不用从头开始进行寻找了。 类别 hash和btree hash 根据字段值生生成一个hash的值 快速的进行定位到对应的行的值 可能会出现相同的值&#xff0c;找到对应的空间会出现对应的值 btree树…

CMA和CNAS是什么?两者有什么用途和区别?

CMA和CNAS是两个不同的概念&#xff0c;它们分别有着自己的用途和区别。 CMA是中国计量认证&#xff08;China Metrology Accreditation&#xff09;的缩写&#xff0c;是根据《中华人民共和国计量法》及其配套法规的规定&#xff0c;由国家质量监督检验检疫总局授权的计量认证…

HTML a标签

<a>标签定义一个超链接。它有如下主要属性&#xff1a; href&#xff1a;指定链接的地址&#xff0c;可以是一个URL、文件路径或锚点。target&#xff1a;指定链接在何处打开。其值包括&#xff1a; _blank&#xff1a;在新窗口或新标签页打开链接。_self&#xff1a;在…