java學習之路----什麼是java的弱引用

夢-尋發表於2013-12-08

原文連結: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

說明物件在建立完成之後,就被垃圾回收了。

相關文章