java中的軟,弱,虛引用介紹與特性分析

java的弱,虛,軟引用介紹

1.弱,虛,軟引用的介紹

對於絕大部分的對象而言,在程式中是存在著一個引用變數引用該對象,這是常見的引用方式,也就是常說的 強引用,對於強引用引用的對象,系統JVM是不會隨意的回收資源,但是區別於強引用,對於記憶體敏感的程式,我們

這個記憶體敏感我也不清楚是啥,書上是這樣說的,個人理解可能就是對於記憶體開支需求比較大的

也常常可以使用java.lang.ref下提供的三個包:

  • SoftReference
  • PhantomReference
  • WeakReference

這三個類分別代表了三種引用,分別是軟引用,虛引用和弱引用。
2.對於四種引用的區別

  • 強引用:代表對象處於可達狀態,不能被系統垃圾回收機制所回收
  • 軟引用:當一個對象只有軟引用的時候,可能被垃圾回收機制所回收,當記憶體空間足夠,就不會回收,記憶體空間不夠就另當別論
  • 弱引用:只要進行垃圾回收,就會對於這個對象進行回收,變為可恢復狀態
  • 對於對象本身沒有太大的影響,甚至對象是感受不到虛引用的存在的,虛引用主要用於跟蹤對象被垃圾回收的狀態,虛引用不能單獨使用,必須結合隊列(ReferenceQueue)聯合使用

對象在記憶體中的三種狀態,分別是可達狀態,可恢復狀態,死亡狀態

除了強引用外,其他三種引用類都有一個get()方法獲取引用的對象

3.對於引用隊列(ReferenceQueue)的介紹

對於軟引用和弱引用,在回收完畢之後,把引用的對象和相關的引用添加到關聯的引用隊列之中
對於虛引用,在回收之前,把對象對應的虛引用添加到相關的隊列之中,這使得可以在對象被回收之前採取行動

軟引用和弱引用可以單獨使用,但是虛引用一般是用來追蹤對象與垃圾回收的狀態,程式可以通過檢查與虛引用相關的引用隊列中是否包含了這個虛引用來了解這個對象是不是快要回收了

弱引用的例子

public static void main(String[]__) throws Exception
	  {
		  //創建一個字元串對象,注意要使用new方法,而不是直接string a=「xxx」,這樣字元串會在常量池導致無法回收
		  String str=new String("山威");
		  //創建一個弱引用,讓弱引用引用這個str
		  ReferenceQueue<String> que=new ReferenceQueue<>();
		  WeakReference<String> wr=new WeakReference<String>(str,que);
		  //切斷str與字元串的聯繫
		  str=null;
		  
		  //在這裡取出弱引用對象
		  System.out.println(wr.get());
		  
		  //在這裡進行記憶體回收
		  System.gc();
		  System.runFinalization();
		  
		  System.out.println(wr.get());
		  
		  //再次從隊列取出來看看
		  System.out.println(que.poll().get());
	  }

在這裡插入圖片描述
這裡是程式碼輸出的結果,可以看到在強制垃圾回收之後,弱引用丟失了對象,而隊列那個嘛,是我加進去試試的,其實引用隊列我也不太會,hhh
記憶體中的樣子請添加圖片描述

虛引用的列子

public static void main(String[]__) throws Exception
	  {
		  //創建一個字元串對象,注意要使用new方法,而不是直接string a=「xxx」,這樣字元串會在常量池導致無法回收
		  String str=new String("山威");
		  //創建一個弱引用,讓弱引用引用這個str
		  ReferenceQueue<String> que=new ReferenceQueue<>();
		 PhantomReference<String> ph=new PhantomReference<String>(str,que);
		  //切斷str與字元串的聯繫
		  str=null;
		  
		  //在這裡取出弱引用對象
		  //不會輸出東西,因為不能使用虛引用訪問對象
		  System.out.println(ph.get());
		  
		  //在這裡進行記憶體回收
		  System.gc();
		  System.runFinalization();
		  
		//回收之後,虛引用進入隊列
		  //再次從隊列取出來看看
		  System.out.println(que.poll()==ph);
	  }

輸出結果
在這裡插入圖片描述
進入隊列之後判斷,所以這裡最後一個輸出是true

4.作用分析

使用這些引用類可以避免在程式執行期間將對象留在記憶體中。如果以軟引用、弱引用或虛引用的方式引用對象,垃圾收集器就能夠隨意地釋放對象。如果希望儘可能減小程式在其生命周期中所佔用的記憶體大小時,這些引用類就很有用處。
必須指出:要使用這些特殊的引用類,就不能保留對對象的強引用;如果保留了對對象的強引用,就會浪費這些引用類所提供的任何好處。 《java瘋狂講義》


//取出弱引用所引用的對象
        obj=wr.get();
        //如果取出的對象為null
        if (obj==null)
        {
            //重新創建一個新的對象,並使用強引用來引用它
            obj=recreateIt();
            //取出弱引用所引用的對象,將其賦給obj變數
            wr=new WeakReference(obj);
        }
        ...//操作obj對象
        //再次切斷obj和對象之間的關聯
        obj=null;

例子也是使用 《java瘋狂講義》的,這書除了講的太細了,其他都好

首發於部落格園(部落格園不能一邊寫一遍瀏覽,所以是寫到csdn搬過來,但是沒在csdn發布的)–2021.10.28