深刻理解JVM虛擬機13:再談四種引用及GC實踐

Java中的四種引用類型

1、背景

Java的內存回收不須要程序員負責,JVM會在必要時啓動Java GC完成垃圾回收。Java以便咱們控制對象的生存週期,提供給了咱們四種引用方式,引用強度從強到弱分別爲:強引用、軟引用、弱引用、虛引用。 前端

2、簡介

1.強引用 StrongReference

StrongReference是Java的默認引用形式,使用時不須要顯示定義。任何經過強引用所使用的對象無論系統資源有多緊張,Java GC都不會主動回收具備強引用的對象。程序員

public class StrongReferenceTest {

	public static int M = 1024*1024;

	public static void printlnMemory(String tag){
		Runtime runtime = Runtime.getRuntime();
		int M = StrongReferenceTest.M;
		System.out.println("\n"+tag+":");
		System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
	}
	
	public static void main(String[] args){
		StrongReferenceTest.printlnMemory("1.原可用內存和總內存");
		
		//實例化10M的數組並與strongReference創建強引用
		byte[] strongReference = new byte[10*StrongReferenceTest.M];
		StrongReferenceTest.printlnMemory("2.實例化10M的數組,並創建強引用");
		System.out.println("strongReference : "+strongReference);
		
		System.gc();
		StrongReferenceTest.printlnMemory("3.GC後");
		System.out.println("strongReference : "+strongReference);

		//strongReference = null;後,強引用斷開了
		strongReference = null;
		StrongReferenceTest.printlnMemory("4.強引用斷開後");
		System.out.println("strongReference : "+strongReference);
		
		System.gc();
		StrongReferenceTest.printlnMemory("5.GC後");
		System.out.println("strongReference : "+strongReference);
		}
}

運行結果:面試


 

2.弱引用 WeakReference

若是一個對象只具備弱引用,不管內存充足與否,Java GC後對象若是隻有弱引用將會被自動回收。算法

public class WeakReferenceTest {
	
	public static int M = 1024*1024;
	
	public static void printlnMemory(String tag){
		Runtime runtime = Runtime.getRuntime();
		int M = WeakReferenceTest.M;
		System.out.println("\n"+tag+":");
		System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
	}
	
	public static void main(String[] args){  
		WeakReferenceTest.printlnMemory("1.原可用內存和總內存");

		//建立弱引用
		WeakReference<Object> weakRerference = new WeakReference<Object>(new byte[10*WeakReferenceTest.M]);   
		WeakReferenceTest.printlnMemory("2.實例化10M的數組,並創建弱引用");
		System.out.println("weakRerference.get() : "+weakRerference.get());
		
		System.gc();
		StrongReferenceTest.printlnMemory("3.GC後");
		System.out.println("weakRerference.get() : "+weakRerference.get());
	}   
}

運行結果:數據庫

 


 

3.軟引用 SoftReference

軟引用和弱引用的特性基本一致, 主要的區別在於軟引用在內存不足時纔會被回收。若是一個對象只具備軟引用,Java GC在內存充足的時候不會回收它,內存不足時纔會被回收。數組

public class SoftReferenceTest {
	
	public static int M = 1024*1024;
	
	public static void printlnMemory(String tag){
		Runtime runtime = Runtime.getRuntime();
		int M = StrongReferenceTest.M;
		System.out.println("\n"+tag+":");
		System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
	}
	
	public static void main(String[] args){
		SoftReferenceTest.printlnMemory("1.原可用內存和總內存");
		
		//創建軟引用
		SoftReference<Object> softRerference = new SoftReference<Object>(new byte[10*SoftReferenceTest.M]);
		SoftReferenceTest.printlnMemory("2.實例化10M的數組,並創建軟引用");
		System.out.println("softRerference.get() : "+softRerference.get());
	  
		System.gc();  
		SoftReferenceTest.printlnMemory("3.內存可用容量充足,GC後");
		System.out.println("softRerference.get() : "+softRerference.get());  

		//實例化一個4M的數組,使內存不夠用,並創建軟引用
		//free=10M=4M+10M-4M,證實內存可用量不足時,GC後byte[10*m]被回收
		SoftReference<Object> softRerference2 = new SoftReference<Object>(new byte[4*SoftReferenceTest.M]);
		SoftReferenceTest.printlnMemory("4.實例化一個4M的數組後");
		System.out.println("softRerference.get() : "+softRerference.get());
		System.out.println("softRerference2.get() : "+softRerference2.get());  
	 } 
}

運行結果:微信

 


 

4.虛引用 PhantomReference

從PhantomReference類的源代碼能夠知道,它的get()方法不管什麼時候返回的都只會是null。因此單獨使用虛引用時,沒有什麼意義,須要和引用隊列ReferenceQueue類聯合使用。當執行Java GC時若是一個對象只有虛引用,就會把這個對象加入到與之關聯的ReferenceQueue中。架構

public class PhantomReferenceTest {

	public static int M = 1024*1024;

	public static void printlnMemory(String tag){
		Runtime runtime = Runtime.getRuntime();
		int M = PhantomReferenceTest.M;
		System.out.println("\n"+tag+":");
		System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");
	}
	
	public static void main(String[] args) throws InterruptedException {
		
		PhantomReferenceTest.printlnMemory("1.原可用內存和總內存");
		byte[] object = new byte[10*PhantomReferenceTest.M];		
		PhantomReferenceTest.printlnMemory("2.實例化10M的數組後");
		
	    //創建虛引用
	    ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();
	    PhantomReference<Object> phantomReference = new PhantomReference<Object>(object,referenceQueue);  
	    
	    PhantomReferenceTest.printlnMemory("3.創建虛引用後");
	    System.out.println("phantomReference : "+phantomReference); 
	    System.out.println("phantomReference.get() : "+phantomReference.get());
	    System.out.println("referenceQueue.poll() : "+referenceQueue.poll());
	    
	    //斷開byte[10*PhantomReferenceTest.M]的強引用
	    object = null;  
	    PhantomReferenceTest.printlnMemory("4.執行object = null;強引用斷開後");
	    
	    System.gc();
	    PhantomReferenceTest.printlnMemory("5.GC後");
	    System.out.println("phantomReference : "+phantomReference); 
	    System.out.println("phantomReference.get() : "+phantomReference.get());
	    System.out.println("referenceQueue.poll() : "+referenceQueue.poll());	    
	   
	    //斷開虛引用
	    phantomReference = null;
		System.gc(); 
		PhantomReferenceTest.printlnMemory("6.斷開虛引用後GC");
	    System.out.println("phantomReference : "+phantomReference);
	    System.out.println("referenceQueue.poll() : "+referenceQueue.poll());	    	
	}
}

運行結果:機器學習

 


 

3、小結

強引用是 Java 的默認引用形式,使用時不須要顯示定義,是咱們平時最常使用到的引用方式。無論系統資源有多緊張,Java GC都不會主動回收具備強引用的對象。 弱引用和軟引用通常在引用對象爲非必需對象的時候使用。它們的區別是被弱引用關聯的對象在垃圾回收時老是會被回收,被軟引用關聯的對象只有在內存不足時纔會被回收。 虛引用的get()方法獲取的永遠是null,沒法獲取對象實例。Java GC會把虛引用的對象放到引用隊列裏面。可用來在對象被回收時作額外的一些資源清理或事物回滾等處理。 因爲沒法從虛引獲取到引用對象的實例。它的使用狀況比較特別,因此這裏不把虛引用放入表格進行對比。這裏對強引用、弱引用、軟引用進行對比:分佈式

引用類型 GC時JVM內存充足 GC時JVM內存不足
強引用 不被回收 不被回收
弱引用 被回收 被回收
軟引用

微信公衆號【黃小斜】大廠程序員,互聯網行業新知,終身學習踐行者。關注後回覆「Java」、「Python」、「C++」、「大數據」、「機器學習」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「筆試」、「面試」、「面經」、「計算機基礎」、「LeetCode」 等關鍵字能夠獲取對應的免費學習資料。

 

微信公衆號【Java技術江湖】一位阿里 Java 工程師的技術小站。(關注公衆號後回覆」Java「便可領取 Java基礎、進階、項目和架構師等免費學習資料,更有數據庫、分佈式、微服務等熱門技術學習視頻,內容豐富,兼顧原理和實踐,另外也將贈送做者原創的Java學習指南、Java程序員面試指南等乾貨資源)

 

相關文章
相關標籤/搜索