强引用、软引用、弱引用、幻象引用有什么区别?

《Java核心技术面试精讲–杨晓峰》学习笔记目录

文章中许多内容都是从此处摘录:https://www.cnblogs.com/heyonggang/p/10254372.html
对这部分内容不太了解,暂时这样吧
Java Reference Objects(待看) http://www.kdgregory.com/index.php?page=java.refobj

文章目录

      • 正文
        • 强引用
        • 软引用
        • 弱引用
        • 幻象引用
        • 扩展部分查看专栏
      • 补充
        • ReferenceQueue
        • Reference

文章有一条留言很有意思

强引用就像大老婆,关系很稳固(JVM不会回收此类对象)。
软引用就像二老婆,随时有失宠的可能,但也有扶正的可能
(JVM会在即将抛出OOM之前回收,被回收后加入引用队列,回收后get返回为null)。
弱引用就像情人,关系不稳定,可能跟别人跑了(JVM只要发现弱引用就会立即回收)。
幻像引用就是梦中情人,只在梦里出现过(在任何时候都可能被垃圾收集器回收,任何时间get都为空)。

正文

  • 不同的引用类型,主要体现的是对象不同的可达性(reachable)状态和对垃圾收集的影响。

强引用

通过关键字new创建的对象所关联的引用就是强引用。**在JVM内存空间不足时,JVM不会回收具有强引用的对象,而是会抛出OOM。**对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略。
例如:
Object obj = new Object()

软引用

软引用通过SoftReference类实现。他可以让对象豁免一些垃圾收集。当内存空间足够的时候,垃圾回收器不会回收它。只有当JVM认定内存空间不足时才会去回收软引用指向的对象。JVM会确保在抛出OOM前清理软引用指向的对象,而且JVM是很聪明的,会尽可能优先回收长时间闲置不用的软引用指向的对象,对那些刚构建的或刚使用过的软引用指向的对象尽可能的保留。基于软引用的这些特性,软引用可以用来实现很多内存敏感点的缓存场景,即如果内存还有空闲,可以暂时缓存一些业务场景所需的数据,当内存不足时就可以清理掉,等后面再需要时,可以重新获取并再次缓存。这样就确保在使用缓存提升性能的同时,不会导致耗尽内存。

应用场景:图片缓存框架中,内存缓存中的图片是以这种引用来保存,使得JVM在发生OOM之前,可以回收这部分缓存

软引用通常可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,java虚拟机就会把这个软引用加入到与之关联的引用队列中。

使用软引用的一个示例
在使用软引用的时候必须检查引用是否为null。因为垃圾收集器可能在任意时刻回收软引用,如果不做是否null的判断,可能会出现NullPointerException的异常。

SoftReference<List<Foo>> ref = new SoftReference<List<Foo>>(new LinkedList<Foo>());
 
// 创建了一个Foo的list集合
List<Foo> list = ref.get();
if (list != null)
{
    list.add(foo);
}
else
{
    //业务代码
} 

弱引用

弱引用通过WeakReference类实现。 弱引用的生命周期比软引用短。弱引用指向的对象是一种十分临近finalize状态的情况,在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

threadlocalmap里的key为弱引用 使用过后 应该remove 否则容易出现oom 因为可能key被回收了 它的值还在

应用场景:一个类发送网络请求,承担callback的静态内部类,则常以虚引用的方式来保存外部类(宿主类)的引用,当外部类需要被JVM回收时,不会因为网络请求没有及时回来,导致外部类不能被回收,引起内存泄漏

幻象引用

幻象引用,也有被说成是虚引用或幽灵引用。幻象引用并不会决定对象的生命周期。即如果一个对象仅持有虚引用,就相当于没有任何引用一样,在任何时候都可能被垃圾回收器回收。不能通过它访问对象,幻象引用仅仅是提供了一种确保对象被finalize以后,做某些事情的机制(如做所谓的Post-Mortem清理机制),也有人利用幻象引用监控对象的创建和销毁。

应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。

扩展部分查看专栏

扩展

补充

ReferenceQueue

引用队列,在检测到适当的可到达性更改后,垃圾回收器将已注册的引用对象添加到该队列中

实现了一个队列的入队(enqueue)和出队(poll还有remove)操作,内部元素就是泛型的Reference,并且Queue的实现,是由Reference自身的链表结构( 单向循环链表 )所实现的。

ReferenceQueue名义上是一个队列,但实际内部并非有实际的存储结构,它的存储是依赖于内部节点之间的关系来表达。可以理解为queue是一个类似于链表的结构,这里的节点其实就是reference本身。可以理解为queue为一个链表的容器,其自己仅存储当前的head节点,而后面的节点由每个reference节点自己通过next来保持即可。

Reference

java.lang.ref.Reference 为 软(soft)引用、弱(weak)引用、虚(phantom)引用的父类。

因为Reference对象和垃圾回收密切配合实现,该类可能不能被直接子类化。
可以理解为Reference的直接子类都是由jvm定制化处理的,因此在代码中直接继承于Reference类型没有任何作用。但可以继承jvm定制的Reference的子类。
例如:Cleaner 继承了 PhantomReference
public class Cleaner extends PhantomReference

参考文献
https://www.cnblogs.com/heyonggang/p/10254372.html
https://www.jianshu.com/p/f86d3a43eec5

你可能感兴趣的:(强引用、软引用、弱引用、幻象引用有什么区别?)