ThreadLocal的内存泄露

最近心血来潮花了一周多时间把周克明先生的《深入理解JAVA虚拟机》的书看完了,没想到自己竟然能这么快的看完,虽不说全部掌握,但绝大部分都已经理解,想想大半年前自己的状态,这半年进步神速,这应该得益于现在的心境,而现在我也会开始写博客,因为我觉得能够很好的把自己掌握的东西表达出来才是真的理解和掌握。

ThreadLocal的内存泄露

前提

在看完书后对JVM产生了浓重的兴趣,我也开始搜寻更多的question去试着解答,所以近期在oschina看到一篇关于“ThreadLocal内存泄露”的文章,于是开始研究ThreadLocal是否会导致内存泄露的问题, 文章的笔者写的非常好,但是有一个最核心的原理没有说出来,并且其中有一段关键的话是让人听得有点含糊的,笔者在这里把实现原理记录下来,说的有出入的地方,也欢迎更多的朋友拍砖指正。

分析ThreadLocal

ThreadLocal内存泄露”文中有一段话:

“每个key都弱引用指向threadlocal. 像上面code中的例子,当把threadlocal实例tl置为null以后,没有任何强引用指向threadlocal实例,所以threadlocal将会被gc回收. 但是,我们的value却不能回收,因为存在一条从current thread连接过来的强引用”

上段话总结的比较精致,可能不好理解,笔者把实现过程记录下来,有利于后面的读者理解: 其实ThreadLocal作为key断掉强引用t1之后 会被GC的真正原因是因为ThreadLocalMap中的Entry 继承了 WeakReference,我们先来看看源码:

static class Entry extends WeakReference<ThreadLocal> {
        Object value;

        Entry(ThreadLocal var1, Object var2) {
            super(var1);
            this.value = var2;
        }
 }

注意:泛型是ThreadLocal对象,并没有包含Entry中的Object value, 且后续并没有再用到这个ThreadLocal,所以ThreadLocal被GC掉了,另外如果不知道WeakReference的,可以去看下Java WeakReference的理解与使用这篇文章

而value并没有被current Thread 保留强引用,Thread里面很明显的强引用是对于 ThreadLocalMap对象!!!~ 真正保证了value是Map中的Entry对象有个Object value 强引用! 那么问题来了既然Entry的Key都extends弱引用,这个地方为什么不把value也实现WeakReference呢?因为一旦key被GC,那么value将不可访问,而value又是强引用,所以很容易导致内存泄露

当然ThreadLocal内存泄露”文中有讲到线程退出的时候肯定会回收这个线程的所有内存,自然ThreadLocalMap作为Thread的一部分也会被回收,但是如果一旦用了线程池,或者线程并没有退出那么很可能会导致内存泄露的问题,所以笔者在这里推荐使用ThreadLocal.get()后,使用对应的ThreadLocal.remove()移除value,确保程序的安全性


注:版权所有转载请注明出处http://my.oschina.net/u/926166/blog/539228


你可能感兴趣的:(java,jvm,threadLocal,内存泄露)