ThreadLocal内存泄漏?

news2024/10/6 5:56:04

ThreadLocal内存泄漏?

在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这样情况发生,增强系统的健壮性。

强引用与弱引用

强引用,使用最普遍的引用,一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。如果想取消强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间就会回收该对象。

弱引用,JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。可以在缓存中使用弱引用。

实现原理

static class ThreadLocalMap {

    static class Entry extends WeakReference<ThreadLocal<?>> {
        /** The value associated with this ThreadLocal. */
        Object value;

        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    ...
   }

ThreadLocal的实现原理,每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。这些对象之间的引用关系如下,

在这里插入图片描述
实心箭头表示强引用,空心箭头表示弱引用

ThreadLocal 内存泄漏的原因
线程池中,一个线程会不断的从队列中拿去任务执行(不发生异常的话),这个线程是会一直存活的,换句话说他的ThreadLocalMap一直都在。如果此时ThreadLocal作为run方法里的局部变量,且ThreadLocalMap的key不声明为弱引用(则为硬引用)。run方法跑完,threadLocal被回收,但是线程不会结束(因为是线程池的线程),ThreadLocalMap不会被回收,对应上一步的生成的Entry还是保留在ThreadLocalMap的数组中,只要Thread不死(ThreadLocalMap就还在),GC就无法回收那个Entry(key,value),然后key不为null,已经没办法判断是不是回收的了。

还是讨论ThreadLocal作为run方法里的局部变量,且ThreadLocalMap的key声明为弱引用。run方法跑完,threadLocal被回收,但是线程不会结束(因为是线程池的线程),ThreadLocalMap不会被回收,对应上一步的生成的Entry还是保留在ThreadLocalMap的数组中。等待某次GC后,Entry的key被回收,变成Entry(null,value),在remove源码中,有对key==null的Entry进行value=null的help GC的操作。在某次调用remove还能再补救一下,相比为硬引用,已经没办法补救了,已经识别不出来哪些是正在需要GC的了。
总结来说,在ThreadLocal为局部变量的时候,不声明为WeekReference,忘记remove了,然后ThreadLocal被回收后,再也没办法确认ThreadLocalMap这个认为是用完的Entry(key,value)节点是不是可以GC了。而弱引用的Entry的key,某次GC后,无用的Entry都被标记为(null, value),此时就能识别出来是泄露的内存。

为什么建议把ThreadLocal声明为static?
这样就保留了ThreadLocal为强引用了,因为他是GCRoot对象,永不可能回收,key(ThreadLocal对象)是不是弱引用已经无所谓了。因为ThreadLocal是静态变量,所以只存在一个ThreadLocal对象,即使是线程池的线程(假设不发生异常,永远存活),这个ThreadLocal对象也只会占用ThreadLocalMap一个Entry的坑位,换句话说,及时我不回收他,我声明的这个对象在一个线程里只占一个Entry的坑位,永不回收问题也不是很大。对比局部变量ThreadLocal,不回收,每跑一次run方法可能就生成一个Entry,只要不调用remove,内存就会一直泄漏下去。

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

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

相关文章

【二十五】【C++】二叉搜索树及其简单实现

二叉搜索树的性质 二叉搜索树&#xff08;BST&#xff09;是一种特殊的二叉树&#xff0c;它具有以下性质&#xff1a; 每个节点都有一个键&#xff08;或值&#xff09;&#xff0c;并且每个节点最多有两个子节点。 左子树上所有节点的键都小于其根节点的键。 右子树上所有…

bugku3

xxx二手交易市场 进去是这样讴歌乱进的页面 查看了一下源代码也没什么 先随便注册一个账号 然后登录 随便看了看&#xff0c;发现可以修改头像 上传文件 随便上传了一个图片 发现他对图片进行了base64加密 解密后得到是 data:image/jpeg;base64 这里重新修改类型为php&a…

栈的实现及其括号匹配问题

栈的实现及其括号匹配问题 一、栈的基本概念及其实现二、栈的数据结构实现三、oj题括号匹配问题解答 一、栈的基本概念及其实现 1.什么是栈&#xff1f;   栈是一种特殊的线性表&#xff0c;只允许栈顶一段插入和删除数据&#xff0c;栈底就是一个容器的底子&#xff0c;栈中…

ubuntu22.04@Jetson Orin Nano之OpenCV安装

ubuntu22.04Jetson Orin Nano之OpenCV安装 1. 源由2. 分析3. 证实3.1 jtop安装3.2 jtop指令3.3 GPU支持情况 4. 安装OpenCV4.1 修改内容4.2 Python2环境【不需要】4.3 ubuntu22.04环境4.4 国内/本地环境问题4.5 cudnn版本问题 5. 总结6. 参考资料 1. 源由 昨天用Jetson跑demo程…

数据恢复软件推荐!简单几步找回丢失数据!

“我真的非常需要一款靠谱的数据恢复软件&#xff01;在对电脑文件进行移动时有些文件被我误删了&#xff0c;在回收站也无法找到&#xff0c;大家有什么比较好的数据恢复软件推荐吗&#xff1f;” 随着数字时代的来临&#xff0c;数据已成为我们生活和工作中不可或缺的一部分。…

微服务-Alibaba微服务nacos实战

1. Nacos配置中心 1.1 微服务为什么需要配置中心 在微服务架构中&#xff0c;当系统从一个单体应用&#xff0c;被拆分成分布式系统上一个个服务节点后&#xff0c;配置文件也必须跟着迁移&#xff08;分割&#xff09;&#xff0c;这样配置就分散了&#xff0c;不仅如此&…

普中51单片机学习(串口通信)

串口通信 原理 计算机通信是将计算机技术和通信技术的相结合&#xff0c;完成计算机与外部设备或计算机与计算机之间的信息交换 。可以分为两大类&#xff1a;并行通信与串行通信。并行通信通常是将数据字节的各位用多条数据线同时进行传送 。控制简单、传输速度快&#xff1…

自然语言编程系列(二):自然语言处理(NLP)、编程语言处理(PPL)和GitHub Copilot X

编程语言处理的核心是计算机如何理解和执行预定义的人工语言&#xff08;编程语言&#xff09;&#xff0c;而自然语言处理则是研究如何使计算机理解并生成非正式、多样化的自然语言。GPT-4.0作为自然语言处理技术的最新迭代&#xff0c;其编程语言处理能力相较于前代模型有了显…

MT5016A-ASEMI大电流整流桥MT5016A

编辑&#xff1a;ll MT5016A-ASEMI大电流整流桥MT5016A 型号&#xff1a;MT5016A 品牌&#xff1a;ASEMI 封装&#xff1a;D-63 最大重复峰值反向电压&#xff1a;1600V 最大正向平均整流电流(Vdss)&#xff1a;50A 功率(Pd)&#xff1a; 芯片个数&#xff1a;4 引脚数…

Python + Selenium —— 元素定位函数 find_element!

WebDriver 中的 find_element() 方法用来查找元素&#xff0c;并返回 WebElement 对象。是 WebDriver 中最常用的方法。 前面提到的八种定位方式都有对应的方法&#xff0c;如find_element_by_id()。 在 WebDriver 中还有一种用法&#xff0c;就是单纯的find_element()。需要…

8款白嫖党必备的ai写作神器,你都知道吗? #AI写作#科技

这些工具不仅可以快速生成高质量的文本内容&#xff0c;还可以根据用户的需求进行个性化定制。它们可以帮助我们节省大量的时间和精力&#xff0c;让我们更加专注于创意和细节的打磨。本文将为大家详细介绍几个AI写作工具&#xff0c;让你在写作领域更上一层楼。 1.元芳写作 …

ASP.NET-实现图形验证码

ASP.NET 实现图形验证码能够增强网站安全性&#xff0c;防止机器人攻击。通过生成随机验证码并将其绘制成图像&#xff0c;用户在输入验证码时增加了人机交互的难度。本文介绍了如何使用 C# 和 ASP.NET 创建一个简单而有效的图形验证码系统&#xff0c;包括生成随机验证码、绘制…

8*4点LED数显/数码管显示驱动控制芯片-VK1650,兼容替代市面1650,提供FAE技术支持

产品品牌&#xff1a;永嘉微电/VINKA 产品型号&#xff1a;VK1650 封装形式&#xff1a;SOP16 概述&#xff1a; VK1650是一种带键盘扫描电路接口的LED驱动控制专用芯片&#xff0c;内部集成有数据锁存 器、LED驱动、键盘扫描等电路。SEG脚接LED阳极&#xff0c;GRID脚接LED阴…

Outlook 中关闭特殊字符显示

故障现象&#xff1a; 不知道什么原因&#xff0c;Outlook发mail时候&#xff0c;突然显示如下的特殊字符&#xff0c;看起来非常不方便&#xff0c;需要关闭; 解决办法&#xff1a; 在Outlook正文里面&#xff0c;输入CtrlShift*&#xff08; 其中*是键盘数字8旁边的那个*&a…

使用Docker部署Docker-Compose-Ui工具并实现公网访问

文章目录 1. 安装Docker2. 检查本地docker环境3. 安装cpolar内网穿透4. 使用固定二级子域名地址远程访问 Docker Compose UI是Docker Compose的web界面。这个项目的目标是在Docker Compose之上提供一个最小的HTTP API&#xff0c;同时保持与Docker Compose CLI的完全互操作性。…

【Unity3D】ASE制作天空盒

找到官方shader并分析 下载对应资源包找到\DefaultResourcesExtra\Skybox-Cubed.shader找到\CGIncludes\UnityCG.cginc观察变量, 观察tag, 观察代码 需要注意的内容 ASE要处理的内容 核心修改 添加一个Custom Expression节点 code内容为: return DecodeHDR(In0, In1);outp…

第十四章[面向对象]:14.3:实例属性

一,认识实例属性 1,什么是实例属性? 实例属性是与类的每个实例相关联的属性。 每个类的实例都可以拥有自己的一组实例属性。 实例属性通常在类的构造方法(通常是__init__方法)内定义,并使用self关键字来访问。 2,实例属性的一个重要特点是每个实例都有自己独立的一组实…

从0到1的私域流量体系搭建,私域操盘手的底层认知升级

一、教程描述 本套私域操盘手教程&#xff0c;大小4.31G&#xff0c;共有12个文件。 二、教程目录 01第一课、私域能力必修&#xff1a;私域大神熟记于心的高阶私域体系.mp4 02第二课、私域IP打造&#xff1a;那些忍不住靠近的私域IP如何打造的.mp4 03第三课、朋友圈经济&…

openEuler二进制安装MySQL8.0.x

一、环境准备 1、系统&#xff1a;openEuler操作系统 2、MySQL版本&#xff1a;MySQL-8.0.36 3、下载地址&#xff1a;https://dev.mysql.com/get/Downloads/MySQL-8.0 二、安装步骤 1、下载glibc版本的MySQL 2、新建用户以安全方式运行进程 [rootnode4 ~]# groupadd -r -g…

基于STL的演讲比赛流程管理系统(个人学习笔记黑马学习)

1、演讲比赛程序需求 1.1比赛规则 学校举行一场演讲比赛&#xff0c;共有12个人参加。比赛共两轮&#xff0c;第一轮为淘汰赛&#xff0c;第二轮为决赛。每名选手都有对应的编号&#xff0c;如 10001~10012比赛方式:分组比赛&#xff0c;每组6个人;第一轮分为两个小组&#xff…