谈谈强引用、软引用、弱引用、幻象引用?

本贴最后更新于 383 天前,其中的信息可能已经时移俗易

我们知道在 Java 中除了基础的数据类型以外,其它的都为引用类型。而 Java 根据其生命周期的长短将引用类型又分为强引用、软引用、弱引用、幻象引用 。正常情况下我们平时基本上我们只用到强引用类型,而其他的引用类型我们也就在面试中,或者平日阅读类库或其他框架源码的时候才能见到。

1.强引用

我们平日里面的用到的 new 了一个对象就是强引用,例如 Object obj = new Object();

当 JVM 的内存空间不足时,宁愿抛出 OutOfMemoryError 使得程序异常终止也不愿意回收具有强引用的存活着的对象!记住是存活着,不可能是你 new 一个对象就永远不会被 GC 回收。

当一个普通对象没有其他引用关系,只要超过了引用的作用域或者显示的将引用赋值为 null 时,你的对象就表明不是存活着,这样就会可以被 GC 回收了。当然回收的时间是不一定的具体得看 GC 回收策略。

2.软引用

软引用的生命周期比强引用短一些。在 JDK 1.2 之后,提供了 SoftReference 类来实现软引用。当 JVM 认为内存空间不足时,就回去试图回收软引用指向的对象,也就是说在 JVM 抛出 OutOfMemoryError 之前,会去清理软引用对象。

image.png

这样就是一个简单的软引用使用方法。通过 get()方法获取对象。

image.png

软引可以与引用队列(ReferenceQueue)联合使用。

当 softObj 软引用的 obj 被 GC 回收之后,softObj 对象就会被塞到 queue 中,之后我们可以通过这个队列的 poll()来检查你关心的对象是否被回收了,如果队列为空,就返回一个 null。反之就返回软引用对象也就是 softObj。软引用一般用来实现内存敏感的缓存,如果有空闲内存就可以保留缓存,当内存不足时就清理掉,这样就保证使用缓存的同时不会耗尽内存。例如图片缓存框架中缓存图片就是通过软引用的。

3.弱引用

回收就会死亡:它的生命周期比软引用还要短,也是通过 get()方法获取对象。被弱引用关联的对象实例只能生存到下一次垃圾收集发生之前。在 GC 的时候,不管内存空间足不足都会回收这个对象。在 JDK 1.2 之后,提供了 WeakReference 类来实现弱引用。

image.png

同样也可以配合 ReferenceQueue 使用,也同样适用于内存敏感的缓存。ThreadLocal 中的 key 就用到了弱引用。

4.虚引用

也称幻象引用,它是最弱的一种引用关系。在 JDK 1.2 之后,提供了 PhantomReference 类来实现虚引用。一个对象实例是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。任何时候可能被 GC 回收,就像没有引用一样。

image.png

无法通过虚引用访问对象的任何属性或者函数。那就要问了要它有什么用?虚引用仅仅只是提供了一种确保对象被 finalize 以后来做某些事情的机制。比如说这个对象被回收之后发一个系统通知啊啥的。

虚引用是必须配合 ReferenceQueue 使用的,具体使用方法和上面提到软引用的一样。主要用来跟踪对象被垃圾回收的活动。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2989 引用 • 8141 回帖 • 596 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    316 引用 • 1389 回帖 • 55 关注
1 操作
ibut 在 2020-11-09 09:39:07 更新了该帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...