1强引用
Object o = new Object()
的赋值 o的引用就是new出来的这个Object
2软引用
通过SoftReference
创建的引用对象就是软引用
软引用对象会在内存不足进行GC的时候会被回收
3弱引用
通过WeakReference
创建的对象就是弱引用
弱引用会在GC时被回收(全部GC还是YoungGC|MinorGC|FullGC)
3.1ThreadLocal内存泄露分析
经典应用ThreadLocal.ThreadLockMap.Entry
的k是一个弱引用
如图②中,ThreadLocalMap
中的k是通过弱引用指向ThreadLocal
对象,在图①中的local
是一个指向ThreadLocal
的强引用,
如果k是强引用的话,当local引用被回收,但是此时k依然引用着ThreadLocal
对象,如图③Thread
类中的threadLocals
,如果对应的线程不被回收,则ThreadLocalMap
会被一直引用着,于此同时Entry
中的k也不会被回收,因为local被回收,k将无法被访问到,但是如果是强引用,k随着线程一直存在,不会被回收,ThreadLocal
对象也会一直存在,但是无法访问到,会导致内存泄露,使用弱引用会在k没有其他强引用的引用后被回收.(当然线程被回收后,k和value也会随着线程的回收被回收掉,但是对于服务器中的监测、网络线程等长期存在的线程强引用则会导致内存的泄露)
3.2为什么ThreadLocal依然存在内存泄露的问题
图①的local被回收之后,ThreadLocalMap
中的k对应的ThreadLocal
对象也会被回收,既然k会变成null,此时会导致value无法被访问到,但是由于线程没有被回收,所以Thread
中的threadLocals
一直存在,导致value无法被回收,因此还是存在内存泄露的问题.
如图②中Entry
的构造函数中,调用WeakReferance
的构造方法,并将k传入,将k作为弱引用.
3.3为什么当前依旧存在内存泄露的问题呢?
既然当前是弱引用对象,即图①的local
被回收之后,ThreadLocalMap
中的k对应的ThreadLocal
对象也会被回收,既然k被回收,那么会导致value无法被访问到,因此还是存在内存泄露的问题.
3.4如果解决内存泄露问题
在使用完ThreadLocal
存储的内容,后调用ThreadLocal
中的remove()
方法,手动将value变为null
4虚引用
虚引用也称幽灵引用或幻影引用,通过PhantomReference
对象创建
如果一个对象的强引用或者软引用消失,那么这个对象会被GC回收,回收前调用其finalize()
方法,如果调用过finalize()
方法后还没有被回收掉,这个对象就会成为一个虚引用对象.
虚引用的值永远访问不到,get()
方法永远返回null
虚引用的创建需要用到一个Queue
,可以通过queue
来检查是否有弱引用被回收,当使用DirectByteBuffer
操作堆外的是否,需要来对堆外回收内存,使用虚引用来监听对象被回收,对象回收后,来进行堆外内存的回收