`
zwt2001267
  • 浏览: 433304 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于java中的强弱引用(WeakReference,SoftReference,PhantomReference)

阅读更多

     关于java中的强弱引用(WeakReferenceSoftReferencePhantomReference

前两天看db4o,看到关于db4o的对象缓存中的对象是weak reference(弱引用),这样对于用户查询出来的大量对象结果,db4o使用弱引用,这样当垃圾回收时可以自己判断并进行垃圾回收。对于weak reference不是很了解,查点资料,整理一下。
对于实现了自动垃圾回收的面向对象语言,都会有关于reference的一些实现,如java中在java.lang.ref中有下面几个类:
Reference
 
   SoftReference
 
   WeakReference
   PhantomReference
 
ReferenceQueue
 
表明了几种引用关系。而这种引用关系和垃圾回收紧密相关。可以看看jdkapi文档中对这几个类的解释也会有一个比较清晰的认识。


1.SoftReference
,软引用对象,在响应内存需要时,由垃圾回收器决定是否清除此对象。软引用对象最常用于实现内存敏感的缓存。 
假定垃圾回收器确定在某一时间点某个对象是软可到达对象。这时,它可以选择自动清除针对该对象的所有软引用,以及通过强引用链,从其可以到达该对象的针对任何其他软可到达对象的所有软引用。在同一时间或晚些时候,它会将那些已经向引用队列注册的新清除的软引用加入队列。 
软可到达对象的所有软引用都要保证在虚拟机抛出 OutOfMemoryError 之前已经被清除。否则,清除软引用的时间或者清除不同对象的一组此类引用的顺序将不受任何约束。然而,虚拟机实现不鼓励清除最近访问或使用过的软引用。 
此类的直接实例可用于实现简单缓存;该类或其派生的子类还可用于更大型的数据结构,以实现更复杂的缓存。只要软引用的指示对象是强可到达对象,即正在实际使用的对象,就不会清除软引用。例如,通过保持最近使用的项的强指示对象,并由垃圾回收器决定是否放弃剩余的项,复杂的缓存可以防止放弃最近使用的项。一般来说,weakReference我们用来防止内存泄漏,保证内存对象被VM回收。

2.WeakReference,弱引用对象,它们并不禁止其指示对象变得可终结,并被终结,然后被回收。弱引用最常用于实现规范化的映射。 
假定垃圾回收器确定在某一时间点上某个对象是弱可到达对象。这时,它将自动清除针对此对象的所有弱引用,以及通过强引用链和软引用,可以从其到达该对象的针对任何其他弱可到达对象的所有弱引用。同时它将声明所有以前的弱可到达对象为可终结的。在同一时间或晚些时候,它将那些已经向引用队列注册的新清除的弱引用加入队列。 softReference多用作来实现cache机制,保证cache的有效性。

3.PhantomReference,虚引用对象,在回收器确定其指示对象可另外回收之后,被加入队列。虚引用最常见的用法是以某种可能比使用 Java 终结机制更灵活的方式来指派 pre-mortem 清除操作。
如果垃圾回收器确定在某一特定时间点上虚引用的指示对象是虚可到达对象,那么在那时或者在以后的某一时间,它会将该引用加入队列。 
为了确保可回收的对象仍然保持原状,虚引用的指示对象不能被检索:虚引用的 get 方法总是返回 null 
与软引用和弱引用不同,虚引用在加入队列时并没有通过垃圾回收器自动清除。通过虚引用可到达的对象将仍然保持原状,直到所有这类引用都被清除,或者它们都变得不可到达。

下面贴一些我写的例子:

ReferenceAndGCExample.java

public class ReferenceAndGCExample {
public static void main(String[] args) {
   // TODO Auto-generated method stub
   YDateProxy ob = new YDateProxy();
   ob.testObj();
   System.gc();
   ob.testObj();
}
}

YDateProxy.java

import java.lang.ref.WeakReference;
import java.util.Date;

public class YDateProxy {
WeakReference wr;

public YDateProxy() {
   wr = new WeakReference(new YDate());
}
public void testObj() {
   if (wr.get() == null)
    System.out.println("obj
已经被清除了
");
   else
    System.out.println("obj
尚未被清除,其信息是
" + wr.get().toString());
}

class YDate extends Date{
   public void finalize() {
    try {
     super.finalize();
    } catch (Throwable e) {
     e.printStackTrace();
    }
   }
}
}

运行结果:
obj
尚未被清除,其信息是 Fri Nov 16 09:08:26 CST 2007
obj
已经被清除了

在两次db.testObj()中,加入System.gc();这时虚拟机进行垃圾回收,弱引用对象被回收,所以第二次访问结果是obj已经被回收了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics