名词介绍
- 强引用:Java中默认的引用类型,一个对象如果具有强引用,那么只要这种引用还存在就不会被GC。
- 软引用:简言之,如果一个对象具有软引用,在JVM发生OOM之前,是不会GC这个对象的,只有JVM内存不足的时候才会被GC。软引用和一个引用队列联合使用,如果软引用所引用的对象被回收之后,该引用就会加入到与之关联的引用队列中。
- 弱引用:如果一个对象只具有弱引用,那么这个对象就会被垃圾回收器GC(被弱引用所引用的对象只能生存到下一次GC之前,当发生GC时,无论当前内存是否足够,弱引用所引用的对象都会被回收掉)。ThrealLocalMap类中的Entry的知识点。弱引用也是和一个引用队列联合使用,如果弱引用的对象被垃圾回收器回收掉,JVM会将这个引用加入到与之关联的引用队列中。若引用的对象可以通过弱引用的get()方法得到,当引用的对象被回收掉之后,再调用get()方法会返回null
- 虚引用:虚引用是所有引用中最弱的一种引用,其存在就是为了将关联虚引用的对象在被GC之后收到一个通知。不能通过get()方法获得其指向的对象
弱引用经典使用场景ThreadLocal
先来看下Thread、ThreadLocal和WeakReference之间的UML类图
阿里规范手册中明确指出【参考】ThreadLocal使用static修饰符修饰,目的是为了所有线程能共用ThreadLocal存储空间,以便节省内存
当我们适应static修饰ThreadLocal时,线程执行完任务回归到线程池中,但此时Thread对象中threadLocals变量(ThreadLocal.ThreadLocalMap)依旧存在,Map中Entry的key(ThreadLocal)由于之前被static修饰,存在强引用和弱引用两种引用类型,是不会被GC回收的,而Map中的value也是一种强引用不会被回收,当该线程下次被复用时,threadLocals存在数据污染,如果再次设置不同的ThreadLocal对象,有可能存在内存泄漏的风险。所以,务必在使用完ThreadLocal对象之后,调用remove()方法,将Map中的key、value和Entry置空,下次GC时能将内存回收掉方便下次分配使用。