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)賦值給某個對象的成員變量。