深入探讨ThreadLocal和对象引用

文章讨论了ThreadLocal在Java中的实现,特别是ThreadLocalMap中的Entry如何使用WeakReference来避免内存泄漏。当ThreadLocal对象仅被Entry的弱引用持有时,垃圾回收器会回收ThreadLocal对象,但Entry由于被map强引用而不会被回收,可能导致value值的内存泄漏。因此,使用完ThreadLocal需调用remove()来清理引用。
摘要由CSDN通过智能技术生成

核心问题:ThreadLocalMap中Entry继承了WeekReference,为什么要这样做?

  1. Hotspot虚拟机下一个类User继承另一个类Person后,在对User类实例化时堆中一共创建了几个对象(不考虑编译优化)?答:一个,调用顺序父类clinit(()->子类clinit()->父类init()->子类init()
  2. 如果创建了两个对象,那么父类对象的指针/引用保存在子类对象的哪块区域的?答:chatgpt说的保存在子类的对象头的,感觉不对,对象头里面不是只有markword、classpoint、数组长度么,chasspointer、数组长度么!
  3. 一个类继承了WeekReference,那么这个类在实例化时,他保存了一个指向其父类WeekReference对象的指针/引用吗?答:继承的类的实例化在只会生成一个对象的情况下,是不存在这种可能的
  4. WeekReference有一个成员变量referent,是对一个对象的弱引用还是对一个对象的强引用的弱引用吗?答:应该是指向了这个对象强引用的弱引用,两个引用指向同一个内存地址,所以==也是为true的
  5. GC时这个被referent引用的对象一旦只被这个referent引用,那么就会被GC回收吗?答:当垃圾回收器开始工作时,无论当前内存是否足够,都会回收到只被弱引用关联的对象。也就是说如果这个弱引用关联的对象被其他对象强引用或者软引用引用着,就不会在本次垃圾收集时被回收
  6. 如果referent引用的ThreadLocal对象不被其他引用引用,就代表其维护的value值也不会再被访问了,那么这个继承了WeekReference类的Entry对象会被回收吗? 答:如果referent会回收,因为entry对象本身被threadLocalMap强引用着,所以不会被回收,只能通过用户代码显式的调用threadLocal.remove()方法才能删除对这个entry对象的引用。

ThreadLocal实现过程:每个线程Thread都有一个ThreadLocalMap的成员变量(Entry[]实现的,以下简称map),在调用一个ThreadLocal的get/set方法时,实际上会拿到当前这个Thread的map,然后对ThreadLocal进行hash取模运算后拿到一个map中的下标,通过这个下标来存取Entry,Entry继承了WeakReference类(简称Reference),这个Reference类有一个referent的成员变量,除此之外Entry有一个value的成员变量,referent作为一个弱引用指向ThreadLocal对象在堆中的内存地址(Java为什么要通过引用来访问对象,通过虚、弱、软、强在垃圾回收时进行不同的处理逻辑),当垃圾回收器工作时,并且ThreadLocal对象只被这个referent弱引用指向着时,那么这个对象就会被回收。因为Entry被map强引用着,所以不会被回收,Entry的value引用所指向的对象被Entry强引用着也不会被回收,所以存在内存泄漏。因此,线程使用完了ThreadLocal需要显式的调用其remove()方法清除对Entry、Value的强引用,这个remove()方法会不管有没有同时清除对Reference对象的软引用

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值