标签:java -- 回收 ThreadLocal 引用 key Entry 内存
内存泄漏
不会再被使用的对象或者变量占用的内存不能被回收,就是内存泄露。
强引用与弱引用
强引用:使用最普遍的引用(New),一个对象具有强引用将不会被GC回收。当内存空间不足时,jvm宁愿抛出OutOfMemoryError错误使程序终止,也不回收这种对象。
弱引用:使用java.lang.ref.WeakReference表示。jvm在进行垃圾回收时,无论内存是否充足,都会回收这种对象。
ThreadLocal的内存泄露分析
ThreadLocal的实现原理:每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例,value为线程变量的副本。
ThreadLocal在没有外部强引用时,发生GC时会被回收,如果创建ThreadLocal的线程一直持续运行,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄露。
那为什么使用弱引用而不是强引用
假如hreadLocalMap的key为强引用,回收ThreadLocal时,因为ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,因而value也不会被回收,导致Entry内存泄漏。
让key(threadLocal对象)为弱引用,自动被垃圾回收,key就变为null了,下次,我们就可以通过Entry不为null,而key为null来判断该Entry对象该被清理掉了。
Entry的key被设计为弱引用就是为了让程序自动地对访问不到的数据进行回收,所以,在访问不到的数据被回收之前,内存泄漏确实是存在的,但是我们不用担心,就算我们不调用remove,ThreadLocalMap在内部的set,get和扩容时都会清理掉泄漏的Entry,内存泄漏完全没必要过于担心
因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。
ThreadLocal正确的使用方法
-
每次使用完ThreadLocal都调用它的remove()方法清除数据
-
将ThreadLocal变量定义成private static,设计为static的,被class对象给强引用,线程存活期间就不会被回收。这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉 。
参考链接:
《提升能力,涨薪可待》-ThreadLocal的内存泄露的原因分析以及如何避免 - 掘金
Java中ThreadLocal的实际用途是啥? - 知乎
谈谈ThreadLocal为什么被设计为弱引用 - 知乎
标签:java,--,回收,ThreadLocal,引用,key,Entry,内存 来源: https://blog.csdn.net/qq_34626094/article/details/120236402
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。