xiao 这个问题看了很多博客,解释都是一个样, 例如这里: ,我看了一下ThreadLocal的源码 这里的Entry 是一个弱引用对象,一段时间后会被回收,回收之后这个value 的引用不也就消失了吗?何来“ThreadLocal中的key 为null,而value还存在强引用“之说?
aukocharlie xiao 弱引用:若对象只被弱引用所引用,则其会被回收 在此处,Entry 本身即为弱引用,所以此处指的是,Entry 的 key 只被 Entry 所引用时,则其会被回收 所以综上,被回收的只是 key , Entry 始终会被 Map 所引用,自然 value 也会被 Entry 强引用,所以有内存泄露的风险 但是 ThreadLocal 有考虑到这点,内部有个 expungeStaleEntries 方法,会在调用 get set remove方法时执行,它会将 key 为 null (即 threadLocal 变量被回收)的 Entry 的 value 清空,便于回收
Tsuko Thread通过中间层ThreadLocal去访问ThreadLocalMap, Map弱引用了ThreadLocal作为key。 ThreadLocal被GC但是Map中对应的Slot没有被释放。可以通过: 定期删除 延迟到某事件发生时删除 Map采用后者. 在set()/get()/remove()中会删除无效的slot. 这也是大多数文章提到的,然后点到为止了(??) 我猜应该是其他threadLocal调用 remove()会告诉Map去遍历删除无效的key value.
xiao 感谢!清楚多了,如果不在每次使用过后ThreadLocal.remove()的话,当前线程再次使用ThreadLocal.set()的时候会重新生成一个新的Entry (因为不能再根据key去定位到原来的Entry了,原来的Entry关联的ThreadLocal 对象由于是WeakReference 过一段时间可能被回收了,再去调用Entry.get()返回的也是null),而原来的那个Entry 相当于没用了,却还占用着内存,当这种情况发送的次数多了之后就会发送OOM! 但问题又来了,我发现只要不用WeakReference 就不存在这样的问题了?
aukocharlie xiao 我发现只要不用WeakReference 就不存在这样的问题了? 不用 WeakReference 的话,Map 会始终引用 Entry,又无法判断 Entry 是否可以回收,那才是真的内存泄露