ThreadLocal真的存在内存泄漏吗?来这里探讨真相吧( 三 )


代码来源链接
注意这里的没有被任何变量引用
但是我们实际的应用场景都是将定义为final,那么我们将上面代码作一些改动
private static final ThreadLocal threadLocal = new ThreadLocal<>();public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException {Thread t = new Thread(()->test("abc",false));t.start();t.join();System.out.println("--gc后--");Thread t2 = new Thread(() -> test("def", true));t2.start();t2.join();}private static void test(String s,boolean isGC){try {threadLocal.set(s);if (isGC) {System.gc();}Thread t = Thread.currentThread();Class clz = t.getClass();Field field = clz.getDeclaredField("threadLocals");field.setAccessible(true);Object ThreadLocalMap = field.get(t);Class tlmClass = ThreadLocalMap.getClass();Field tableField = tlmClass.getDeclaredField("table");tableField.setAccessible(true);Object[] arr = (Object[]) tableField.get(ThreadLocalMap);for (Object o : arr) {if (o != null) {Class entryClass = o.getClass();Field valueField = entryClass.getDeclaredField("value");Field referenceField = entryClass.getSuperclass().getSuperclass().getDeclaredField("referent");valueField.setAccessible(true);referenceField.setAccessible(true);System.out.println(String.format("弱引用key:%s,值:%s", referenceField.get(o), valueField.get(o)));}}} catch (Exception e) {e.printStackTrace();}}
输出结果:
可以看到我们验证的结论是正确的,也是网上所说的key被回收为null的发生内存泄漏其实是错误的
总结 只有在线程池下面才会发生内存泄漏中的key为对的弱引用,只是为了解决回收问题所谓的内存泄漏问题,不是说key为null导致,只是说我们在使用因为线程没有被回收,而我们对该变量不想再使用了,而一直存在没有被回收,就算发生了内存泄漏 。所以在使用注意使用完调用方法 后续
这里主要是对网上讨论的内存泄漏问题做了一个必要的辟谣 。还有一些核心源码也没有分析,限于篇幅,感兴趣自己可以自己去探讨,比如中的黄金分割数等等
这里也推荐一篇分析比较全的博客
【ThreadLocal真的存在内存泄漏吗?来这里探讨真相吧】地址