0

0

Java中的ThreadLocal怎么导致内存泄漏的_底层Entry弱引用分析

P粉602998670

P粉602998670

发布时间:2026-03-17 08:35:03

|

992人浏览过

|

来源于php中文网

原创

ThreadLocal 的 Entry 使用弱引用是为了在线程复用场景下避免内存泄漏,其 key 设为弱引用可被 GC 回收,而 value 仍强引用,需显式调用 remove() 清理。

java中的threadlocal怎么导致内存泄漏的_底层entry弱引用分析

ThreadLocal 的 Entry 为什么是弱引用

因为 ThreadLocal 的核心设计目标是:让每个线程持有自己的一份副本,且在线程结束时能自动清理。但 JVM 无法主动感知线程生命周期,所以 JDK 用弱引用来解耦 ThreadLocal 实例和 Entry 的生命周期——Entry 的 key 是 WeakReference<threadlocal></threadlocal>,value 却是强引用。

这意味着:只要外部不再持有该 ThreadLocal 实例(比如被置为 null 或超出作用域),key 就可能被 GC 回收,Entry 变成“key == null”的脏 entry。但 value 还活着,且线程的 ThreadLocalMap 仍持有它。

  • 不是所有弱引用都安全;这里只弱了 key,没弱 value
  • GC 不会主动扫描并清理整个 ThreadLocalMap,得靠后续的 get/set/remove 触发探测和清理
  • 线程长期存活(如线程池中的 worker 线程)时,这个“脏 entry”就容易堆积

内存泄漏的真实触发场景

泄漏不是发生在 ThreadLocal 被创建时,而是当它被“遗弃”后,又没人调用 remove(),且线程持续复用 —— 典型于 Web 容器或自定义线程池。

例如 Tomcat 中一个请求用 ThreadLocal<connection></connection> 存数据库连接,但没在 filter 或 finally 里调用 threadLocal.remove();下个请求复用同一线程,旧的 Connection 对象就卡在 map 里出不去。

立即学习Java免费学习笔记(深入)”;

NameGPT名称生成器
NameGPT名称生成器

免费AI公司名称生成器,AI在线生成企业名称,注册公司名称起名大全。

下载
  • 静态 ThreadLocal 字段最容易出问题:类加载器卸载不了,key 永远不为 null?错——静态引用本身不会阻止 key 被回收,但 value 引用的对象可能持有着 ClassLoader
  • 线程池中未清理的 ThreadLocal,value 若是大对象(如 byte[]、缓存 Map),泄漏更明显
  • set(null) 不能代替 remove():它只是把 value 设为 null,Entry 还在,key 也没变,map size 不减

怎么正确清理 ThreadLocal

别依赖“线程结束自动清理”,线程池让这假设失效。必须显式调用 remove(),且时机要对。

  • 在 try-finally 块末尾调用 threadLocal.remove(),不要只在 catch 里做
  • 如果是 Servlet 过滤器,确保 doFilter() 执行完后清理,哪怕发生异常也要清理
  • 避免在 lambda 或匿名内部类里直接 capture ThreadLocal 并忘记清理(尤其在异步回调中)
  • 使用 InheritableThreadLocal 更危险:子线程继承后若不清理,泄漏面更大

排查和验证泄漏的方法

光看代码逻辑不够,得看运行时行为。重点不是“有没有 remove”,而是“有没有被执行到”。

用 jstack + jmap 配合分析:jmap -histo:live <pid> 查看 ThreadLocalMap$Entry 数量是否随请求增长;再用 jmap -dump:format=b,file=heap.hprof <pid>,用 MAT 打开,按 incoming references 查哪些 Entry 的 key == null,再看它们的 value 持有哪些大对象。

  • ThreadLocalMap 本身不会被频繁 GC,但它的 value 若是长生命周期对象,会拖慢老年代回收
  • 某些监控工具(如 Arthas)可动态 attach 并执行 ognl '@java.lang.Thread@currentThread().threadLocals' 查当前 map 内容
  • 注意:JDK 9+ 对 ThreadLocalMap 做了部分优化(如 resize 时顺便 clean),但不改变根本机制,该清理还得清理

真正难的不是理解弱引用,是在线程复用场景下,把清理逻辑嵌进所有可能的退出路径里——漏一条,就可能积少成多。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
如何配置Tomcat环境变量
如何配置Tomcat环境变量

配置Tomcat环境变量需要在系统中添加CATALINA_HOME变量,并将Tomcat的安装路径添加到PATH变量中。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

117

2023.10.26

idea如何集成Tomcat
idea如何集成Tomcat

idea集成Tomcat的步骤:1、添加Tomcat服务器配置;2、配置项目部署;3、运行Tomcat服务器;4、访问项目;5、注意事项;6、关闭Tomcat服务器。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

173

2024.02.23

怎么查看Tomcat源代码
怎么查看Tomcat源代码

查看Tomcat源代码的步骤:1、下载Tomcat源代码;2、在IDEA中导入Tomcat源代码;3、查看源代码;4、理解Tomcat的工作原理;5、参与社区和贡献;6、注意事项;7、持续学习和更新;8、使用工具和插件。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

99

2024.02.23

常见的tomcat漏洞有哪些
常见的tomcat漏洞有哪些

常见的tomcat漏洞有:1、跨站脚本攻击;2、跨站请求伪造;3、目录遍历漏洞;4、缓冲区溢出漏洞;5、配置漏洞;6、第三方组件漏洞。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

170

2024.02.23

tomcat日志乱码怎么解决
tomcat日志乱码怎么解决

tomcat日志乱码的解决办法:1、修改tomcat的日志编码设置;2、检查ide的编码设置;3、检查操作系统的编码设置;4、使用过滤器处理日志;5、检查外部系统的编码设置;6、检查文件编码方式等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

159

2024.02.23

weblogic和tomcat有哪些区别
weblogic和tomcat有哪些区别

weblogic和tomcat的区别:1、功能;2、性能;3、规模;4、价格;5、安全性;6、配置和管理;7、社区支持;8、集成能力;9、升级和更新;10、可靠性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

200

2024.02.23

tomcat和nginx有哪些区别
tomcat和nginx有哪些区别

tomcat和nginx的区别:1、应用领域;2、性能;3、功能;4、配置;5、安全性;6、扩展性;7、部署复杂性;8、社区支持;9、成本;10、日志管理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

245

2024.02.23

tomcat启动闪退怎么解决
tomcat启动闪退怎么解决

tomcat启动闪退的解决办法:1、检查java环境;2、检查环境变量配置;3、检查端口被占用;4、检查配置文件编码;5、检查启动时需要的配置文件;6、检查相关文件是否丢失;7、检查防火墙和杀毒软件设置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

169

2024.02.23

chatgpt使用指南
chatgpt使用指南

本专题整合了chatgpt使用教程、新手使用说明等等相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.03.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.5万人学习

C# 教程
C# 教程

共94课时 | 11.5万人学习

Java 教程
Java 教程

共578课时 | 83.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号