前言
在看 JDK 中 ThreadLocal 源码时接触到了弱引用 WeakReference,在这次的笔记中记录下强引用、弱引用、软引用和虚引用的概念与区别。
四种引用的级别由高到低依次为:
Strong Reference > Soft Reference > Weak Reference > Phantom Reference
强引用(Strong Reference)
强引用是最常使用的引用,任何被强引用所引用的对象都不能被垃圾回收器回收。当内存空间不足,JVM 就会抛出 OutOfMemoryError 错误。
1 | Object obj = new Object(); |
变量 obj 就是该 Object 对象的一个强引用。只有强引用消失,对象才能被 GC 回收。
如果在一个方法的内部有一个强引用,这个引用保存在 Java 栈中,而真正的引用内容(Object)保存在 Java堆中。 当这个方法运行完成后,就会退出方法栈,则引用对象的引用数为0,这个对象会被回收。
弱引用(Weak Reference)
相比于软引用,具有弱引用的对象拥有更短暂的生命周期。当一个对象只有弱引用指向它时,垃圾回收器不管当前内存是否足够,都会进行回收。
在 ThreadLocal 中的 ThreadLocalMap 的 key 就被设计成了弱引用类型,在 JDK 中另一个使用弱引用的例子是WeakHashMap,它是除 HashMap 和 TreeMap 之外Map接口的另一种实现。WeakHashMap中的 key 也是弱引用类型。
软引用(Soft Reference)
软引用用来描述一些有用但是非必需的对象。如果一个对象只具有软引用,当内存空间足够时垃圾回收器就不会回收它。如果内存空间不足了,才会回收这些对象的内存。
软引用用来描述一些有用但并不是必需的对象,比如可用来实现内存敏感的高速缓存。
虚引用(Phantom Reference)
虚引用不同于其余三种引用,也无法通过虚引用获得对象的一个实例,虚引用并不会决定对象的生命周期。
如果一个对象仅持有虚引用,那么它就和没有任何引用一样,为一个对象设置虚引用关联的唯一目的就是希望这个对象被 GC 回收时能收到一个系统通知,即用来跟踪对象被垃圾回收器回收的活动。
虚引用与软引用和弱引用的区别在于:
虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。
总结
引用类型 | 何时会被垃圾回收 | 用途 | 生命周期 |
---|---|---|---|
强引用 | 从不 | / | JVM停止运行时终止 |
弱引用 | 当内存不足时 | 缓存 | 内存不足时终止 |
软引用 | 正常GC时 | 缓存 | GC后终止 |
虚引用 | 正常GC时 | 跟踪对象的垃圾回收 | GC后终止 |
一个对象的生命周期: