Java引用类型原理

Java引用类型原理

引用类型

JVM将引用类型分为以下4中:

  • 强引用(FinalReference)
  • 软引用(SoftReference )
  • 弱引用(WeakReference )
  • 虚引用(PhantomReference )

Reference

Reference类是Java.lang.ref包里的一个抽象类

public abstract class Reference<T> {
    //引用的对象
    private T referent;        
    //回收队列,由使用者在Reference的构造函数中指定
    volatile ReferenceQueue<? super T> queue;
     //当该引用被加入到queue中的时候,该字段被设置为queue中的下一个元素,以形成链表结构
    volatile Reference next;
    //在GC时,JVM底层会维护一个叫DiscoveredList的链表,存放的是Reference对象,discovered字段指向的就是链表中的下一个元素,由JVM设置
    transient private Reference<T> discovered;  
    //进行线程同步的锁对象
    static private class Lock { }
    private static Lock lock = new Lock();
    //等待加入queue的Reference对象,在GC时由JVM设置,会有一个java层的线程(ReferenceHandler)源源不断的从pending中提取元素加入到queue
    private static Reference<Object> pending = null;
}

强引用(FinalReference)

强引用是指创建一个对象并它赋值给一个引用,引用是存在JVM中的栈(还有方法区)中的。具有强引用的对象,垃圾回收器绝对不会去回收它,直到内存不足以分配时,抛出OOM。大多数情况,我们new一个对象,并把它赋值给一个变量,这个变量就是强引用。
Object obj = new Object();

软引用(SoftReference)

软引用描述一些还有用但非必需的对象,具有软引用关联的对象,内存空间足够时,垃圾回收器不会回收它。当内存不足时(接近OOM),垃圾回收器才会去决定是否回收它。

Object obj = new Object();
SoftReference<Object> softRef = new SoftReference(obj);
// 使用 softRef.get() 获取软引用所引用的对象
Object objg = softRef.get();

软引用实现内存缓存

弱引用(WeakReference )

弱引用描述非必需对象,但它的强度比软引用更弱一些。WeakReference对其引用的对象并无保护作用,当垃圾回收器进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。弱引用一般用于实现canonicalizing mappings (正规化映射),典型的应用是WeakHashMap。

  Object obj = new Object();
  ReferenceQueue<Object> refQueue = new ReferenceQueue<Object>();
  WeakReference<Object> weakRef = new WeakReference<Object>(obj, refQueue);

虚引用(PhantomReference )

虚引用也被称为幽灵引用或幻引用,它是最弱的一种引用关系。虚引用并不会影响对象的GC,而且并不可以通过PhantomReference对象取得一个引用的对象。虚引用唯一的作用则是利用其必须和ReferenceQueue关联使用的特性,当其绑定的对象被GC回收后会被推入ReferenceQueue,外部程序可以通过对此队列轮询来获得一个通知,以完成一些目标对象被GC后的清理工作。
PhantomReference 的构造方法,与SoftReference和WeakReference不同,他的构造必须传入一个ReferenceQueue

public PhantomReference(T referent, ReferenceQueue<? super T> q) {
    super(referent, q)
;}

严格的说,虚引用是会影响对象生命周期的,如果不做任何处理,只要虚引用不被回收,那其引用的对象永远不会被回收。所以一般来说,从ReferenceQueue中获得PhantomReference对象后,如果PhantomReference对象不会被回收的话(比如被其他GC ROOT可达的对象引用),需要调用clear方法解除PhantomReference和其引用对象的引用关系。

DirectByteBuffer中是用虚引用的子类Cleaner.java来实现堆外内存回收的,后续会写篇文章来说说堆外内存的里里外外。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值