文章目录Java中的引用类型一、强引用Strong Reference二、软引用Soft Reference三、弱引用Weak Reference四、虚引用Phantom ReferenceJava中的引用类型在 Java 中当我们写下 Object obj new Object(); 时obj 是一个引用new Object() 才是对象本体。可以把引用想象成一根绳子对象就是绳子另一端拴着的气球。只要有绳子拉着气球就不会飞走不会被 GC 回收。Java 提供了四种不同强度的引用类型由强到弱依次为强引用、软引用、弱引用、虚引用。合理使用它们可以更好地管理内存实现缓存、防止内存泄漏等场景。一、强引用Strong Reference强引用是 Java 中最常见的引用类型也就是我们平时直接 new 出来的对象赋值。ObjectobjnewObject();// obj 是强引用只要强引用还存在垃圾收集器就永远不会回收掉被引用的对象。即使内存快要爆了JVM 抛出 OutOfMemoryError 也不会去动它ObjectobjnewObject();// 强引用气球被拉着// 即使内存紧张这个对象也绝对安全objnull;// 主动把绳子剪断// 现在这个对象没有强引用了GC 可以回收二、软引用Soft Reference软引用通过 java.lang.ref.SoftReference 类实现它比强引用弱一级。SoftReferenceMyObjectsoftRefnewSoftReference(newMyObject());软引用就像一根弹性皮筋。当 JVM 内存充足时垃圾收集器不会回收软引用指向的对象但当内存不足、即将抛出 OutOfMemoryError 时JVM 会先回收软引用指向的对象把内存腾出来。ObjectstrongObjnewObject();SoftReferenceObjectsoftRefnewSoftReference(strongObj);strongObjnull;// 切断强引用只剩软引用System.out.println(GC前softRef.get());// 大概率能获取到System.gc();// 内存充足时GC 不会回收软引用对象System.out.println(GC后内存充足softRef.get());// 通常还在// 如果不断分配内存直到 OOMJVM 会清理软引用使用场景内存敏感的缓存比如图片缓存、网页缓存。内存充足时直接从缓存拿内存紧张时自动释放不会导致 OOM。需要可丢弃的中间数据比如地图应用中的瓦片数据重建成本较高但可丢弃。三、弱引用Weak Reference弱引用是通过 java.lang.ref.WeakReference 类来创建的WeakReferenceMyObjectweakRefnewWeakReference(newMyObject());弱引用就像一根头发丝。虽然也能牵着气球但力量非常微弱。当 JVM 进行垃圾回收时无论当前内存是否充足都会立刻回收掉只有弱引用指向的对象。publicclassWeakReferenceDemo{publicstaticvoidmain(String[]args){// 创建一个强引用ObjectstrongObjnewObject();// 创建一个弱引用指向这个对象WeakReferenceObjectweakRefnewWeakReference(strongObj);System.out.println(GC前弱引用获取weakRef.get());// 能拿到对象strongObjnull;// 切断强引用现在只剩弱引用了System.gc();// 建议JVM进行垃圾回收System.out.println(GC后弱引用获取weakRef.get());// 大概率输出 null}}适用场景缓存系统适合实现自动清理的缓存。普通缓存如 HashMap中即使 Key 对应的对象已经没用了只要缓存不清除对象就永远不会被 GC 回收容易造成内存泄漏。而使用弱引用作为 Key如 JDK 提供的 WeakHashMap当 Key 的外部强引用消失后GC 会自动回收 Key对应的 Value 也会从缓存中移除不需要手动清理。对象池用于管理对象池中的非核心对象对象池本身用强引用持有核心对象而用弱引用持有一些不常用、可重建的扩展对象。当内存紧张触发 GC 时这些弱引用指向的对象会被回收释放内存真正需要时再重新创建。避免内存泄漏当一个对象不应该被长期引用时使用弱引用可以防止该对象被意外地保留从而避免潜在的内存泄漏。例如ThreadLocalMap 的 Entry 使用弱引用指向 ThreadLocal 对象。当 ThreadLocal 外部强引用被置为 null 后GC 会自动回收它防止 ThreadLocal 本身泄漏。四、虚引用Phantom Reference虚引用通过 java.lang.ref.PhantomReference 类实现它是最弱的引用类型。ReferenceQueueMyObjectqueuenewReferenceQueue();PhantomReferenceMyObjectphantomRefnewPhantomReference(newMyObject(),queue);虚引用就像根本不存在的绳子。无论有没有虚引用对象被 GC 回收时几乎不受影响。 虚引用必须和引用队列ReferenceQueue一起使用它的 get() 方法永远返回 null。虚引用的唯一作用就是当对象被垃圾收集器回收时能够收到一个系统通知。JVM 会将关联的虚引用加入到引用队列中程序可以通过监控这个队列来得知对象即将被回收从而在回收之后做一些资源清理如释放堆外内存。适用场景堆外内存管理如 DirectByteBuffer当 Java 堆内的对象被回收时通过虚引用通知 JVM 去释放堆外的 native 内存