原文地址
https://mp.weixin.qq.com/s/8Emvbmbn1CgBPjddETEjMA
其实handler的泄漏问题已经写烂了。
这篇文章,我觉得写得好的地方是,把每个gc root的引用路径写得很清楚,图也有。
尤其是 ThreadLocal这个路径。
虽然我还是没有读太懂,我尝试理解一下
先讲ThreadLocalMap的结构
这个map不是真正的map,而是一个Entry[] 数组
每一个Entry包含一个弱引用的ThreadLocal跟value
这个ThreadLocal呢,本质是一个去处理 thread私有的类(有点像废话)
ThreadLocal封装一个方法,createMap
线程私有嘛,
Thread的全局变量sThreadLocal,
t.sThreadLocal = 一个map = Entry[]
之后这个thread里的所有该线程私有的值都往这个map(数组)里存。
ThreadLocal.set(, 就是先去拿当前线程。
所以本质上一直是Thread在做操作,thread是通过threadLocal去操作ThreadLocalMap,为什么是这个关系?我的理解是。。源码里,ThreadLocalMap是ThreadLocal的静态内部类。哈哈哈哈
最终,因为looper就保存在ThreadLocalMap里,looper就成为了thread的私有值。
一个looper对应一个msq,最终就完成整个引用。
还有一个需要理解
“当弱引用的 key 实例因为 GC 发生会被切断和 Map 的引用关系,但直到下一次手动执行 Entry 的 set、get 或 remove 前,value 都没被置为 null。这段时间 value 都被强引用着,造成隐患。
本处 Looper 持有的实例 sThreadLocal 是静态的,进程结束之前都不会被回收,不可能发生上述提及的 key 被回收 value 被孤立的情况。
简言之,Looper 的 ThreadLocal 不会导致内存泄漏”
假设存了一个looper,虽然key,也就是threadlocal,可以切断跟这个数组的联系。但是looper其实作为值,一直存在Entry数组里。
只不过threadlocal切不断。