-
Notifications
You must be signed in to change notification settings - Fork 45.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ThreadLocal 内存泄露问题是怎么导致的? #2579
Comments
内部存储数据的并不是static class Node<K,V> implements Map.Entry<K,V> |
整理后, 以threadlocal的set源码为例子:
在getMap中可看到,通过 在map.set和createMap中,并没有真正存储key,而是通过threadlocal的hash值进行离散计算得到坐标,最终存储于类型为 这也是Entry为何是弱引用的原因,因为可能会出现《null,v》的情况。这里虽然解决了内存泄漏的问题,但是似乎可能会导致Entry提前被回收? 查询得知可达性分析会有一条链路从threadlocal.get()方法所获得的变量,也就是间接可达,换句话说会考虑方法上的引用链条,而并非单纯是变量的直接引用。 |
重点在于key并非是弱引用,只是v作为map的直接引用无法被回收,因此使其成为了弱引用类型,并在set、get方法中做了一系列安全措施。 |
确认之后,欢迎提交一下PR哈,我可以帮你review。 |
其中key为强引用在源码中可以看到,是使用threadlocak变量作为key,也就是this,而threadlocalMap是作为线程thread的成员变量进行存储。深入到threadlocalMap的源码发现使用内部类Entry数组作为存储数据,这个Entry才是继承了弱引用的类。
所谓的内存泄露实际上是由于无限制的创造threadlocal变量,但是value由于在map中可以被gcroot到,不会清除。因此选择使用了弱引用自动清除。
这里看上去似乎依然有问题,如果value引用由于gcroot不会被清除,那么key似乎也同样不会被清除?
请注意,作为存储数据的map类并不是<k,V>的map类,不会真正存储key,而是通过key的hash值进行扰动函数之类的离散计算,得到坐标,也就是说真正存储的只有Value。
int i = key.threadLocalHashCode & (len-1);
The text was updated successfully, but these errors were encountered: