导致JVM内存泄露的ThreadLocal详解

这篇具有很好参考价值的文章主要介绍了导致JVM内存泄露的ThreadLocal详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

很常见的关于ThreadLocal的面试题的问法:

1.说说你对ThreadLocal的理解。

2.ThreadLocal 是什么?有哪 些使用场景?什么是线程局部变量?

3.ThreadLocal内存泄漏分析与解决方案。

ps:想理解好ThreadLocal,必须先得理解好JVM的内存模型

多个线程共同操作一个共享变量,一定会引发并发问题,那么解决的方法就是对代码进行同步,比如synchronized关键字,但是ThreadLocal换了一种思路:让每个线程都拥有共享变量的副本,这样就不会引发多线程并发问题了。

ThreadLocal 是一个本地线程副本变量工具类,在每个线程中都创建了一个  ThreadLocalMap 对象,简单说 ThreadLocal 就是一种以空间换时间的做法, 每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。通过这种方 式,避免资源在多线程间共享。

使用方法很简单:

导致JVM内存泄露的ThreadLocal详解

T initialValue(),set(T value) ,T get() ,remove() 是比较常用的方法,尤其是set(T value)和get()

使用场景:跨方法的参数传递,例如:数据库连接Conn,平时我们要保证事务,并没有看到service或者dao的方法参数中有conn,其实就是通过ThreadLocal来传递的。还有skywalking中的traceId也是用ThreadLocal来实现的。

线程局部变量是局限于线程内部的变量,属于线程自身所有,不在多个线程间共 享。Java 提供 ThreadLocal 类来支持线程局部变量,是一种实现线程安全的方式。但是在管理环境下(如 web 服务器)使用线程局部变量的时候要特别小 心,在这种情况下,工作线程的生命周期比任何应用变量的生命周期都要长。任 何线程局部变量一旦在工作完成后没有释放,Java 应用就存在内存泄露的风 险。

ThreadLocal内存泄漏分析

导致JVM内存泄露的ThreadLocal详解

 在ThreadLocal类中有一个静态内部类ThreadLocalMap,这个Map就是用来存储线程局部变量数据的,底层是一个Entry的数组,注意这个Entry的键 是一个弱引用,而且键类型是ThreadLocal的类型导致JVM内存泄露的ThreadLocal详解

这里又涉及到一道重要的面试题:

Java 中都有哪些引用类型? 强软弱虚

1 强引用:发生 gc 的时候不会被回收。 
2 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。
3 弱引用:有用但不是必须的对象,在下一次GC时会被回收。 
4 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,
  用PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。

这个ThreadLocalMap在Thread类中用到了,是Thread的一个成员变量

导致JVM内存泄露的ThreadLocal详解

 导致JVM内存泄露的ThreadLocal详解

虚拟机栈中的栈帧会不断的出栈,而且当一个任务运行结束后,虚拟机栈会销毁, 那么下图中的引用就没有了

导致JVM内存泄露的ThreadLocal详解

 ThreadLocal对象就剩下一个虚引用引用着了,那么gc之后 ThreadLocal对象就没有了,导致JVM内存泄露的ThreadLocal详解

 只剩下这么多了,大家都知道线程池中的线程是生命周期很长的,那这部分永远都占用着内存空间,就会导致内存泄漏。

所以线程池和ThreadLocal结合使用的时候一定要注意。

总结:

ThreadLocal造成内存泄漏的原因?

ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,而 value 是强引用。所 以,如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候,key 会 被清理掉,而 value 不会被清理掉。这样一来,ThreadLocalMap 中就会出现key 为null的Entry。假如我们不做任何措施的话,value 永远无法被GC 回收,这个 时候就可能会产生内存泄露。ThreadLocalMap实现中已经考虑了这种情况,在 调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。使用完 ThreadLocal方法后 最好手动调用remove()方法。

ThreadLocal内存泄漏解决方案?

1.每次使用完ThreadLocal,都调用它的remove()方法,清除数据。 

2.将ThreadLocal变量尽可能定义成static final 类型的,避免频繁创建ThreadLocal实例。这样可以保证程序中一直存在ThreadLocal的强引用,也能保证任何时候都能通过ThreadLocal的弱引用访问Entry中的Value值。

补充:下面是弱引用的例子

package cn.tulingxueyuan.xiaoshanshan.base.threadlocal;

import java.lang.ref.WeakReference;

public class Yinyong {

    public static void main(String[] args) {

        User user = new User() ;
//        User user1 = user;
        WeakReference<User> user1 = new WeakReference<>(user);
        System.out.println(user);
        user =null ;
        System.gc();
        System.out.println("gc 完成 ...");

//        System.out.println(user1);
        System.out.println(user1.get());
    }

    static class User{

        String name ;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

运行结果:

导致JVM内存泄露的ThreadLocal详解文章来源地址https://www.toymoban.com/news/detail-494238.html

到了这里,关于导致JVM内存泄露的ThreadLocal详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • pytorch 训练过程内存泄露/显存泄露debug记录:dataloader和dataset导致的泄露

    微调 mask-rcnn 代码,用的是 torchvision.models.detection.maskrcnn_resnet50_fpn 代码,根据该代码的注释,输入应该是: images, targets=None (List[Tensor], Optional[List[Dict[str, Tensor]]]) - Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]] 所以我写的 dataset 是这样的: 大概思路是: 先把所有的标注信息读入内存

    2024年02月14日
    浏览(49)
  • (线程池)多线程使用场景--es数据批量导入、数据汇总、异步调用;如何控制某个方法允许并发访问线程的数量;对ThreadLocal的理解及实现原理、源码解析、ThreadLocal的内存泄露问题

    CountDownLatch(闭锁/倒计时锁) 用来进行线程同步协作,等待所有线程完成倒计时(一个或者多个线程,等待其他多个线程完成某件事情之后才能执行) 其中构造参数用来初始化等待计数值 await() 用来等待计数归零 countDown() 用来让计数 减一 多线程使用场景一:( es数据批量导

    2024年04月25日
    浏览(65)
  • 【JVM】Java内存泄露的排查思路?

    Java内存泄露(Memory Leak)是指在Java程序中,无用的对象占用了 堆内存 ,但无法被垃圾回收器回收释放,从而导致可用内存逐渐减少,最终可能导致内存耗尽或性能下降的问题。 说明一般对于内存泄漏。都是针对 堆 的。 程序一般出现内存泄漏会有 两个状态 一是一启动导致

    2024年02月13日
    浏览(47)
  • 一次Python本地cache不当使用导致的内存泄露

    近期一个大版本上线后,Python编写的api主服务使用内存有较明显上升,服务重启后数小时就会触发机器的90%内存占用告警,分析后发现了本地cache不当使用导致的一个内存泄露问题,这里记录一下分析过程。 该cache大概实现代码如下: 如上述代码,该LocalCache核心在于一个存储

    2024年02月11日
    浏览(38)
  • Go坑:time.After可能导致的内存泄露问题分析

    Go 中 time.After 可能导致的内存泄露 go v1.20.4 time 包中有 3 个比较常用的定时函数:NewTicker,NewTimer 和 time.After: NewTimer : 表示在一段时间后才执行,默认情况下执行一次。如果想再次执行,需要调用 time.Reset() 方法,这时类似于 NewTicker 定时器了。可以调用 stop 方法停止执行。

    2024年02月02日
    浏览(53)
  • 用jprofiler来分析 jvm 堆 内存泄露,fullgc

    jvm 命令和工具_个人渣记录仅为自己搜索用的博客-CSDN博客   方法1: 重新设置堆后,重启,复现.   方法2:  切割  官网文档 JProfiler Help - HPROF snapshots heap walker教学: 用jprofile查看hprof文件_hprof jprofile_java老张的博客-CSDN博客 通识教学: JVM监控及诊断工具GUI篇之JProfiler_每天都要进步一

    2024年02月08日
    浏览(92)
  • 注意避坑!Java 内部类持有外部类会导致内存泄露。。。

    本文介绍 Java 内部类持有外部类导致内存泄露的原因以及其解决方案。 为什么内部类持有外部类会导致内存泄露 非静态内部类会持有外部类,如果有地方引用了这个非静态内部类,会导致外部类也被引用,垃圾回收时无法回收这个外部类(即使外部类已经没有其他地方在使

    2024年02月09日
    浏览(51)
  • 内存溢出、内存泄露的概述及常见情形

    java doc 中对 Out Of Memory Error 的解释是,没有空闲内存,并且垃圾收集器也无法提供更多内存。 JVM 提供的内存管理机制和自动垃圾回收极大的解放了用户对于内存的管理,由于 GC(垃圾回收)一直在发展,所有一般情况下,除非应用程序占用的内存增长速度非常快,造成垃圾

    2024年01月21日
    浏览(48)
  • .NET 6 在 Win7 系统证书链错误导致 HttpWebRequest 内存泄露

    本文记录我将应用迁移到 dotnet 6 之后,在 Win7 系统上,因为使用 HttpWebRequest 访问一个本地服务,此本地服务开启 https 且证书链在此 Win7 系统上错误,导致应用内存泄露问题。本文记录此问题的原因以及调查过程 核心原因是在 CRYPT32.dll 上的 CertGetCertificateChain 方法存在内存泄

    2024年02月06日
    浏览(49)
  • 【Jvm】性能调优(拓展)Jprofiler如何监控和解决死锁、内存泄露问题

    Jprofilers是针对Java开发的 性能分析工具(免费试用10天) , 可以对Java程序的 内存,CPU,线程,GC,锁 等进行监控和分析 , 本人IDEA版本是 2020.2.2 ,选择的Jprofiler版本是 12.0 (早期的版本是纯英文的, 12.0支持中文 ,安装主要考虑是否与IDEA插件兼容即可) 进入Jprofiler官网下载 - Jprofiler 版本这

    2024年02月19日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包