Java Reference

1、Reference对象和被引用的对象

 首先需要理解Reference对象和被引用的对象的区分。 Object obj =new Object();Reference<Object> objRef = new SoftReference(obj);

 被引用的对象指的是obj这个对象,Reference对象指的是objRef。

Java中的三种常见Reference类型:SoftReference、WeakReference和PhantomReference中有关GC的说明,针对的都是被引用的对象。


SoftReference:内存不足时,回收被引用的对象。jvm保证在内存溢出之前已经回收了被SoftReference引用的对象的空间。

WeakReference:正常GC时就可以回收,是否回收无法保证

PhantomReference:比上面两种还要弱的引用,所以应该也是正常GC时就可以回收,何时回收无法保证。

注意这里回收的都是这个被引用的对象,而不是Reference对象本身。实际上Reference对象本身是作为一个强引用而存在的(个人理解)。 所以实际的效果就是,被引用的对象被回收,但我们仍然可以获取Reference对象。


2、Reference和ReferenceQueue

其实每个Reference对象都有一个对应的ReferenceQueue,用来存储Reference对象。一个ReferenceQueue对象可以被多个Reference共享。

关于ReferenceQueue的作用,Oracle的官方文档上给出的描述如下

“ Reference queues, to which registered reference objects are appended by the garbage collector after the appropriate reachability changes are detected. ”

当被引用的对象被GC回收之后,GC会把Reference对象添加到队列中。因此,可以这样理解,在队列中的Reference对象,它们引用的对象被GC回收。而不在队列中的,它们引用的对象则还没有被GC回收。这个队列的存在,可以帮助开发者执行一些与被引用对象相关联的数据清理的动作。

比如说有一个文件对象,我们想在这个文件对象被GC回收之后,同时将这个文件从磁盘上删除。这样就可以从ReferenceQueue来获取那些引用的文件被GC回收了的Reference对象,并进行文件的清理动作 --- 这就是tomcat的FileCleaningTracker的实现原理。
     

3、Reference的生命周期

如果一个Reference在创建的时候,有指定了正常可用的ReferenceQueue,那么这个Reference对象便会经历4个生命周期

Active  -->  Pending --> Enqueued --> Inactive

Active状态下被引用的对像还没有被GC回收

Pending 被引用的对象被GC回收后,如果Reference对象创建的时候有指定ReferenceQueue,就进入Pending状态,等待被放入ReferenceQueue中

Enqueued  进入了ReferenceQueue队列

Inactive  从ReferenceQueue中被取出

如果在创建ReferenceQueue的时候没有指定队列,这个Reference就会使用默认的ReferenceQueue.Null队列,生命周期直接由  Active 进入 Inactive

ps:Reference内部有一个pending队列,GC只是把对象添加到这个队列中。Reference有一个后台线程去从pending队列中取出Reference对象,添加到ReferenceQueue中。


4、GC和进入ReferenceQueue的顺序

(这部分内容来自大神Ethan Nicholas的博客)
     
     在简单的模型中,进入了ReferenceQueue的Reference对象所引用的目标对象已经被回收,但实际上对于WeakReference和PhantomReference之间还是存在一定的差别,主要在于,进入队列和GC操作的先后顺序。在这一点上,SoftReference和WeakReference是相同的

     对于WeakReference来说,进入ReferenceQueue是在目标对象真正被GC之前,所以这个时候有可能通过重写finalize()方法来重新获得目标对象

     对于PhantomReference来说,当目标对象被真正GC回收之后,才会进入到ReferenceQueue中,根本无法重新获得目标对象


5、Reference扩展

除了直接使用jdk提供的三种Reference之外,开发人员还可以通过继承SoftReference、WeakReference或PhantomReference来添加自定义的功能,但不能够直接继承Reference。


下面是一篇关于Reference的使用的文章



来自大神Ethan Nicholas的博客文章 ---- 内容很全面




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值