当前位置: 首页 > news >正文

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方法释放内存空间即可。

相关文章:

ThreadLocal内存泄漏问题

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

微服务基础概念【内含图解】

目录 拓展补充: 单体架构 分布式架构 面向服务的体系结构 云原生 微服务架构 什么是微服务? 微服务定义 拓展补充: 单体架构 单体架构:将业务的所有功能集中在一个项目中开发,最终打成一个包部署 优点&#x…...

Dockerfile创建 LNMP 服务+Wordpress 网站平台

文章目录 一.环境及准备工作1.项目环境2.服务器环境3.任务需求 二.Linux 系统基础镜像三.docker构建Nginx1.建立工作目录上传安装包2.编写 Dockerfile 脚本3.准备 nginx.conf 配置文件4.生成镜像5.创建自定义网络6.启动镜像容器7.验证 nginx 四.docker构建Mysql1. 建立工作目录…...

消息中间件篇

消息中间件篇 RabbitMQ 如何保证消息不丢失 面试官: RabbitMQ如何保证消息不丢失 候选人: 嗯!我们当时MYSQL和Redis的数据双写一致性就是采用RabbitMQ实现同步的,这里面就要求了消息的高可用性,我们要保证消息的不…...

基本定时器

1.简介 1. 基本定时器 TIM6 和 TIM7 包含一个 16 位自动重载计数器 2. 可以专门用于驱动数模转换器 (DAC), 用于触发 DAC 的同步电路 3. 16 位自动重载递增计数器 4. 16 位可编程预分频器 5. 计数器溢出时, 会触发中断/DMA请求 从上往下看 1.开始RCC供给定时器的时钟 RCC_APB1…...

MySQL 中文全文检索

创建索引(MySQL 5.7.6后全文件索引可用WITH PARSER ngram,针对中文,日文,韩文) ALTER TABLE 表 ADD FULLTEXT 索引名 (字段) WITH PARSER ngram;或者CREATE FULLTEXT INDEX 索引名 ON 表 (字段) WITH PARSER ngram; …...

Redis——list类型详解

概要 Redis中的list类型相当于双端队列,支持头插,头删,尾插,尾删,并且列表中的内容是可以重复的。 如果搭配使用rpush和lpop,那么就相当于队列 如果搭配使用rpush和rpop,那么就相当于栈 lpu…...

npm 安装 git 仓库包

安装 #v1.0.0 代表版本, 例如打了仓库一个tag叫v1.0.0; 如果不指定版本则默认是最新的代码 npm install githttp://mygitlab.xxxx.net/chengchongzhen/hex-event-track.git#v1.0.0在项目根目录执行以下命令, 此时你的代码会被链接到npm的全局仓库, 类似执行了 npm install xxx …...

问题来了!你知道你穿的防砸劳保鞋的保护包头都是什么材料

防砸劳保鞋是较为常见的一种劳保鞋,用于作业过程中保护工人的脚,减少或避免被坠落物、重物砸伤或压伤脚部的工作鞋。防砸安全鞋鞋前头装有防护包头,具有耐压力和抗冲击性能。主要适用于矿山、机械、建筑、钢铁、冶金、运输等行业。 你穿的防砸…...

计算机网络-物理层(三)编码与调制

计算机网络-物理层(三)编码与调制 在计算机网络中,计算机需要处理和传输用户的文字、图片、音频和视频,它们可以统称为消息 数据是运输信息的实体,计算机只能处理二进制数据,也就是比特0和比特1。计算机中…...

Linux面试笔试题(6)

91、6块300G的硬盘做raid5,新的设备容量是多大(C) A 900G B 1800G C 1500G D 300G 6300G−300G 1500G 由于一块硬盘用于奇偶校验,所以设备容量将是1500G. Raid 5是一种磁盘阵列,将数据分散到多个硬盘上以提高性能和可…...

qt中窗口的布局

qt中窗口的布局 常用的窗口布局方式使用拖拽控件的方式调用窗口布局使用Widget控件完成窗口布局布局中嵌套布局demo(制作登录页面) 如果不使用窗口布局,会带来的后果: 控件可能显示不出来不能按照期望的大小显示不能跟随窗口进行…...

玄子Share - HTML Emmet 语法详细介绍

玄子Share - HTML Emmet 语法详细介绍 以下Emmet语法 基于WebStorm 2023.2演示 Emmet 语法介绍 Emmet 是一种缩写语法,旨在简化 HTML 和 CSS 的编写。它基于 CSS 选择器的语法结构,通过输入特定的缩写,可以快速生成 HTML 结构。 Emmet 语法…...

Linux上安装和使用git到gitoschina和github上_亲测

Linux上安装和使用git到gitoschina和github上_亲测 git介绍与在linux上安装创建SSHkey在git-oschina使用maven-oschina使用在github使用maven-github使用组织与仓库 【git介绍与在linux上安装】 Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何…...

合宙Air724UG LuatOS-Air LVGL API--简介

为何是 LVGL LVGL 是一个开源的图形库,它提供了创建嵌入式 GUI 所需的一切,具有易于使用的图形元素、漂亮的视觉效果和低内存占用的特点。 LVGL特点: 强大的 控件 :按钮、图表、列表、滑动条、图像等 高级图形引擎:动…...

「Vue|网页开发|前端开发」01 快速入门:用vue-cli快速写一个Vue的HelloWorld项目

本文主要介绍如何用vue开发的标准化工具vue-cli快速搭建一个符合实际业务项目结构的hello world网页项目并理解vue的代码文件结构以及页面渲染流程。 文章目录 一、准备工作:安装node.js二、项目搭建创建项目目录全局安装vue-cli使用Webpack初始化项目启动项目学会…...

7.5.tensorRT高级(2)-RAII接口模式下的生产者消费者多batch实现

目录 前言1. RAII接口模式封装生产者消费者2. 问答环节总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。 本次课程学习 tensorRT 高级-RAI…...

华为OD-最大括号深度

题目描述 一个合法的括号匹配序列有以下定义: 1、空串""是一个合法的括号匹配序列 2、如果"X"和"Y"都是合法的括号匹配序列,"XY"也是一个合法的括号匹配序列 3、如果"X"是一个合法的括号匹配序列,那么"(X)"也是一…...

【Leetcode】108. 将有序数组转换为二叉搜索树

一、题目 1、题目描述 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例1: 输入:nums = [-10,-3,0,5,9] 输出:[0,-3,9,-1…...

【树莓派打怪升级】:玩转个人Web世界!

文章目录 概述使用 Raspberry Pi Imager 安装 Raspberry Pi OS设置 Apache Web 服务器测试 web 站点安装静态样例站点 将web站点发布到公网安装 Cpolarcpolar进行token认证生成cpolar随机域名网址生成cpolar二级子域名将参数保存到cpolar配置文件中测试修改后配置文件配置cpola…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

ArcPy扩展模块的使用(3)

管理工程项目 arcpy.mp模块允许用户管理布局、地图、报表、文件夹连接、视图等工程项目。例如,可以更新、修复或替换图层数据源,修改图层的符号系统,甚至自动在线执行共享要托管在组织中的工程项。 以下代码展示了如何更新图层的数据源&…...

基于Uniapp的HarmonyOS 5.0体育应用开发攻略

一、技术架构设计 1.混合开发框架选型 (1)使用Uniapp 3.8版本支持ArkTS编译 (2)通过uni-harmony插件调用原生能力 (3)分层架构设计: graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...

Ubuntu 可执行程序自启动方法

使用 autostart(适用于桌面环境) 适用于 GNOME/KDE 桌面环境(如 Ubuntu 图形界面) 1. 创建 .desktop 文件 sudo vi ~/.config/autostart/my_laser.desktop[Desktop Entry] TypeApplication NameMy Laser Program Execbash -c &…...