ThreadLocal导致内存泄漏分析以及解决方案

场景A、假设ThreadLocalMap中的key使用了强引用,那么会出现内存泄漏吗 ?


1、假设在业务代码中使用完ThreadLocal对象,ThreadLocalRef引用 会被回收了


2、但因为ThreadLocalMap的Entry中key强引用了ThreadLocal对象,造成该对象无法被回收


3、在没有手动删除这个Entry以及当前 CurrentThread线程对象依然运行的前提下,

始终有强引用链 CurrentThreadRef引用--->CurrentThread线程对象--->ThreadLocalMap-->Entry(Entry中的key指向ThreadLocal对象);


所以Entry没法被回收,同时导致new ThreadLocal()对象也没法被回收,导致内存泄漏


场景B、假设ThreadLocalMap中的key使用了弱引用

使用完 ThreadLocal对象 ,threadLocalRef引用 会被回收,但因为ThreadLocalMap的Entry中key只是弱引用了ThreadLocal对象。所以threadlocal对象同时也可以被回收,

此时 Entry 中的 key = null。但没有手动删除这个 Entry 或者 CurrentThread 依然运行,依然存在强引用链,value 不会被回收,而这块 value 永远不会被访问到,

也会导致 value 内存泄漏


三、两个主要原因:

   1、 没有手动删除这个 Entry
   2、CurrentThread 依然运行


根本原因:ThreadLocalMap 是 Thread的一个属性,生命周期跟 Thread 一样长,如果没有手动删除对应 Entry 就会导致内存泄漏


解决方法:使用完 ThreadLocal 中存储的内容后将它 remove 掉就可以


ThreadLocal 内部解决方法:在 ThreadLocalMap 中的 set/getEntry 方法中,通过线性探测法对 key 进行判断,如果 key 为 null(ThreadLocal 为 null)会对 Entry 进行垃圾回收。

所以使用弱引用比强引用多一层保障,就算不调用 remove,也有机会进行 GC

posted @ 2024-06-06 23:40  jock_javaEE  阅读(61)  评论(0)    收藏  举报