垃圾收集器回收對象的依據和時機

Java中的引用:算法

Java中將引用分爲強引用、軟引用、弱引用、虛引用4種,強度依次減弱。
強引用:Object obj = new Object(),只要強引用還存在,垃圾收集器就永遠不會回收這些引用關聯着的對象。
軟引用:用來描述一些還有用但並不是必需的對象。
	在系統將要發生內存溢出異常前,垃圾收集器纔會去回收這些軟引用關聯着的對象。jdk1.2以後,提供了SoftReference類來實現軟引用。
弱引用:和軟引用同樣,也是描述一些還有用但並不是必須的對象,只是它的強度更弱一些。
	當垃圾收集器工做時,不管當前內存是否夠用,都會回收掉只被弱引用關聯的對象。jdk1.2以後,提供了WeakReference類來實現軟引用。
虛引用:是最弱的一種引用,一個對象是否有虛引用的存在,徹底不會對其生存時間構成影響,也沒法經過虛引用來取得一個對象實例。
	設置虛引用的惟一目的:在這個對象被垃圾收集器回收時獲得一個系統通知。

判斷對象是否存活的算法:this

1)引用計數算法:
	概念:給對象添加一個引用計數器,每當有一個地方引用它時,計數器就加1;當引用失效時,計數器就減1;當計數器爲0時,對象就不能再使用了。
	說明:Java虛擬機裏面沒有采用 引用計數算法 來管理內存。緣由:不能解決對象之間相互循環引用的問題
	案例:
		ReferenceCountingGC{
		
			public Object instance = null;
			
			// 這個成員屬性的惟一意義就是佔用一些內存,以便在GC日誌中能夠明顯地看出是否被回收過
			private byte[] bigBlock = new byte[1024 * 1024];
			
			public static void testGC() {
				ReferenceCountingGC objA = new ReferenceCountingGC();
				ReferenceCountingGC bojB = new ReferenceCountingGC();
				
				objA.instance = objB;
				objB.instance = objA;
				
				objA = null;
				objB = null;
				
				// 假設在這行發生GC,那麼objA和objB是否被回收呢?
				System.gc();
			}
		}
		
		由運行結果能夠看出:虛擬機並無由於這兩個對象相互引用就不去回收它們。說明:虛擬機不是經過引用計數算法來判斷對象是不是存活的。

2)可達性分析算法(根搜索算法):
	概念:從根節點開始向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象與根節點之間不存在任何引用鏈時,則證實此對象是不可用的。
	根對象的斷定:
		1)虛擬機棧(棧幀中的本地變量表)中引用的對象、本地方法棧中JNI(即native方法)引用的對象。
		2)方法區中:類靜態屬性引用的對象、常量引用的對象。

一個對象被回收要通過兩次標記:線程

第一次標記:
	若是一個對象在進行可達性分析後沒有發現與根對象間存在引用鏈,那麼這個對象將被第一次標記,並進行判斷:判斷此對象是否有必要去執行finalize()方法。
		1)若是:對象沒有覆蓋finalize()方法,或者finalize()方法已經被調用過了,虛擬機就不會執行該對象的finalize()方法,直接回收該對象。
		2)若是:對象覆蓋了finalize()方法,而且finalize()方法沒有被調用過,那麼:
			1>這個對象將會放置在一個叫作F-Queue 的隊列中,稍後(在第二次標記以前),會有一個由虛擬機自動創建的、低優先級的Finalizer線程去執行該對象的finalize()方法。				2>注意:這裏的「執行」是指虛擬機會觸發這個方法,可是並不保證會等待這個方法運行結束。緣由:若是某個對象執行finalize()方法花費的時間比較長,或者發生了死循環,這樣的話就極可能會致使F-Queue隊列中其它的對象永久等待,若是JVM要等待它運行結束,則有可能會致使整個內存回收系統崩潰。

第二次標記:
	在第一次標記後,GC將對 F-Queue 中的對象進行第二次標記,若是對象在finalize()方法中成功拯救本身,那麼這個對象將被移出」即將回收「的那個集合。若是沒有在finalize()方法中救出本身,那麼它將被GC回收。
	注:在finalize()方法中拯救本身的方法:只要從新與引用鏈上的任何一個對象創建關聯便可。例如:將本身(this)賦值給某個對象的成員變量。
相關文章
相關標籤/搜索