java学习之路----什么是java的弱引用

来源:互联网 发布:张峰 java精品课程 编辑:程序博客网 时间:2024/06/05 17:05

原文链接:http://blog.csdn.net/javastudyr/article/details/17205075

 Java从1.2版本开始引入了4种引用,这4种引用的级别由高到低依次为:

  强引用  >  软引用  >  弱引用  >  虚引用

⑴强引用(StrongReference)
   强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

⑵软引用(SoftReference)

   如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

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

⑶弱引用(WeakReference)

   弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

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

⑷虚引用(PhantomReference)

   “虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。

   虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之 关联的引用队列中。


由于引用和内存回收关系紧密。下面,先通过实例对内存回收有个认识;然后,进一步通过引用实例加深对引用的了解。
我们首先来建立一个类:
public class MyDate extends Date{
     public MyDate(){
          
     }
     
     //我们来重写finalize,因为finalize函数 在JvM回收内存的时候会调用,但是JVM并不保证回收的时候一定会调用
     
     @Override
     protected void finalize() throws Throwable {
     
           super.finalize();
          
          System. out.println(this .getTime());
     }

     @Override
     public String toString() {
     
           return "Date" +this.getTime();
     }
          
}

再来建立一个消耗内存的测试类

     public class ReferenceTest {
     public ReferenceTest(){
          
     }
     //这个方法的目的是来消耗内存
     public static void drainMemory(){
          String array[]= new String[1024*10];
           for(int i=0;i<1024*10;i++){
               for(int j='a' ;j<'z' ;j++){
                   array[i]=array[i]+( char)j;
              }
          }
     }
     
}

我们下面来分情况来测试一下

1.清除对象
public class Test {
     public static void main(String[] args) {
          MyDate myDate=new MyDate();
          myDate= null;
     }

}

结果无输出

说明date=null,但是JVM并没有执行垃圾回收操作

2.显示的调用垃圾回收

public class Test {
     public static void main(String[] args) {
          MyDate myDate=new MyDate();
          myDate= null;
          System. gc();//设为空后,去自动调用垃圾回收
     }

}
结果:
1386430828594

说明垃圾回收机制调用了finalize()方法

3.隐式的调用垃圾回收
public class Test {
     public static void main(String[] args) {
          MyDate myDate=new MyDate();
          myDate= null;
          ReferenceTest. drainMemory();//我们来造成内存的大量消耗
     }

}

结果:
1386431068074


说明调用了垃圾回收机制(内存的大量消耗造成了垃圾回收自动调用),我们得出结论,在内存充足的情况下,除非你显示的调用垃圾回收机制,否则它不会进行垃圾回收,在内存不足的情况下,JVM会自动调用垃圾回收


我们在来看看java对引用的分类

     强引用:

     public class Test {
     public static void main(String[] args) {
          MyDate myDate=new MyDate();//强引用
          System. gc();
     }

}
结果:
无输出,说明虽然我们显示的调用了垃圾回收,但是mydate是强引用,所以不会被回收

     软引用

public class Test {
     public static void main(String[] args) {
           SoftReference ref =new SoftReference(new MyDate());//创建一个软引用
          ReferenceTest. drainMemory();
     }

}

结果无所出:

说明在内存不足的情况下,软引用会被停止

弱引用:

public class Test {
     public static void main(String[] args) {
           WeakReference ref =new WeakReference(new MyDate());
          ReferenceTest. drainMemory();
     }

}

结果:
1386431868012

说明在J垃圾回收的时候,弱引用被停止

虚引用:
public class Test {
     public static void main(String[] args) {
     
           ReferenceQueue queue=new ReferenceQueue();
          
           PhantomReference ref =new PhantomReference(new MyDate(), queue);
           //ReferenceTest.drainMemory();
          
     System.gc();
     }

}
结果:
1386432527842

说明对象在创建完成之后,就被垃圾回收了。