Java垃圾回收

垃圾回收機制特性

  • 垃圾回收機制只負責回收堆內存中的對象,不會回收任何物理資源(例如數據庫連接,網絡IO等資源)
  • 程序無法精確控制垃圾回收的運行,垃圾回收會在合適的時候進行。
  • 在垃圾回收機制回收任何對象之前,總會先調用該對象的finalize()方法,該方法可能使該對象重新復活,從而導致垃圾回收機制取消。也能在這個方法內回收垃圾回收機制無法回收的物理資源.

堆gc

對象在內存中的狀態

  • 可達狀態:當有一個對象被創建後,若有一個以上的引用變量引用它,則這個對象在程序中處於可達狀態,程序可通過引用變量來調用該對象的屬性和方法。
  • 可恢復狀態:如果程序中某個對象不再有任何引用變量引用該對象,該對象就進入了可恢復狀態。在這個狀態下,jvm會準備回收該對象所佔用的內存,在回收該對象之前,會調用所有可恢復狀態對象的finalize()方法進行資源清理。但是如果在調用finalize()方法時重新讓一個引用變量引用該對象,則這個對象會再次變爲可達狀態;否則該對象將進入不可達狀態。
  • 不可達狀態:當對象與所有引用變量的關聯都被切斷,且系統已經調用所有對象的finalize()方法後依然沒有使該對象變成可達狀態,那麼這個對象將永久性地失去引用,最後變成不可達狀態。只有當一個對象處於不可達狀態時,系統纔會真正回收該對象所佔的資源。
    三種狀態之間的轉換
    在這裏插入圖片描述
    以下代碼實現了把可恢復狀態的對象變成可達狀態的對象。
public class FinalizeTest {

    public static FinalizeTest f;

    public static void main(String[] args) throws InterruptedException {
        new FinalizeTest();

        Runtime.getRuntime().gc();
        //如果沒有休眠的話。就會有可能沒有發生GC 從而不會調用finalize方法 這樣 f就會出現空指針異常
        Thread.sleep(200);
        f.info();
    }

    private void info() {
        System.out.println("測試該對象仍讓存在");
    }
    public void finalize(){
        // 讓對象在可恢復狀態 重新獲得引用 變成
        // 可達狀態
        f =this;
    }
}

可達狀態需要可達性分析來判斷對象是否存活。

可達性分析

以GCroot 爲起點,從這些節點開始向下遍歷。走過了路徑稱爲引用鏈。 如下圖所示。Object5,Object6 就是不可達的。
在這裏插入圖片描述

引用

定義:如果reference類型的數據中存儲的數值代表的是另一塊內存的起始地址,就稱這塊內存代表着一個引用。
關於引用對象的設計目的:

當內存空間還足夠是,則能保存在內存之中;如果內存空間在進行垃圾收集後還是非常緊張,則可以拋棄這些對象。

爲了實現這個目標在jdk1.2中將這種引用進行了擴展成爲了四種引用:
強引用,軟引用,弱引用,虛引用。

強引用

程序創建一個對象,並把這個對象賦給一個引用變量,程序通過該引用變量來操作實際的對象。當一個對象被一個或一個以上的引用變量所引用時,它處於可達狀態,不可能被系統垃圾回收機制回收。

軟引用

軟引用需要通過SoftReference類來實現,當一個對象只有軟引用時,它有可能被垃圾回收機制回收。對於只有軟引用的對象而言,當系統內存空間足夠時,它不會被系統回收,程序也可使用該對象;當系統內存空間不足時,系統可能會回收它。軟引用通常用於對內存敏感的程序中。

弱引用

弱引用通過WeakReference類實現,弱引用和軟引用很像,但弱引用的引用級別更低。對於只有弱引用的對象而言,當系統垃圾回收機制運行時,不管系統內存是否足夠,總會回收該對象所佔用的內存。當然,並不是說當一個對象只有弱引用時,它就會立即被回收——正如那些失去引用的對象一樣,必須等到系統垃圾回收機制運行時纔會被回收。

虛引用

虛引用通過PhantomReference類實現,虛引用完全類似於沒有引用。虛引用對對象本身沒有太大影響,對象甚至感覺不到虛引用的存在。如果一個對象只有一個虛引用時,那麼它和沒有引用的效果大致相同。虛引用主要用於跟蹤對象被垃圾回收的狀態,虛引用不能單獨使用,虛引用必須和引用隊列(ReferenceQueue)聯合使用。

引用隊列

根據設計引用的需求:
Reference對象已經不再具有存在的價值,需要一個適當的清楚機制,避免大量引用對象帶來的內存泄漏.所以引用隊列裏面都是存放的可以被銷燬的引用對象。

引用類型 被gc的時間 用途 生存時間 存入引用隊列
強引用 不會gc 對象的一般狀態 程序停止 不會進入隊列
軟引用 當內存不足時 對象緩存 內存不足時終止 沒有指向的對象後
弱引用 正常gc時 對象緩存 gc後 沒有指向的對象後
虛引用 正常gc時 跟蹤對象gc gc後 準備gc指向對象之前

方法區gc

廢棄常量

沒有對象引用常量池的該常量,就可以叫做廢棄常量

無用的類:

  • 該類所有的實例都已經被回收。
  • 加載該類的ClassLoader已經被回收
  • 沒有任何引用

這兩種就是在方法區中的gc的對象。

參考數據
《瘋狂java講義》
《深入理解Java虛擬機》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章