1. 程式人生 > >java基礎之垃圾回收機制

java基礎之垃圾回收機制

Java引入了垃圾回收機制,令C++程式設計師最頭疼的記憶體管理問題迎刃而解。Java程式設計師可以將更多的精力放到業務邏輯上而不是記憶體管理工作上,大大的提高了開發效率。

垃圾回收過程

  任何一種垃圾回收演算法一般要做兩件基本事情:

  1. 發現無用的物件

  2. 回收無用物件佔用的記憶體空間。

  垃圾回收機制保證可以將“無用的物件”進行回收。無用的物件指的就是沒有任何變數引用該物件。Java的垃圾回收器通過相關演算法發現無用物件,並進行清除和整理。

垃圾回收相關演算法

  1. 引用計數法

  堆中每個物件都有一個引用計數。被引用一次,計數加1. 被引用變數值變為null,則計數減1,直到計數為0,則表示變成無用物件。優點是演算法簡單,缺點是“迴圈引用的無用物件”無法別識別。

2. 引用可達法(根搜尋演算法)

  程式把所有的引用關係看作一張圖,從一個節點GC ROOT開始,尋找對應的引用節點,找到這個節點以後,繼續尋找這個節點的引用節點,當所有的引用節點尋找完畢之後,剩餘的節點則被認為是沒有被引用到的節點,即無用的節點。

分代垃圾回收機制,是基於這樣一個事實:不同的物件的生命週期是不一樣的。因此,不同生命週期的物件可以採取不同的回收演算法,以便提高回收效率。我們將物件分為三種狀態:年輕代、年老代、持久代。JVM將堆記憶體劃分為 Eden、Survivor 和 Tenured/Old 空間。

  1. 年輕代

  所有新生成的物件首先都是放在Eden區。 年輕代的目標就是儘可能快速的收集掉那些生命週期短的物件,對應的是Minor GC,每次 Minor GC 會清理年輕代的記憶體,演算法採用效率較高的複製演算法,頻繁的操作,但是會浪費記憶體空間。當“年輕代”區域存放滿物件後,就將物件存放到年老代區域。

  2. 年老代

  在年輕代中經歷了N(預設15)次垃圾回收後仍然存活的物件,就會被放到年老代中。因此,可以認為年老代中存放的都是一些生命週期較長的物件。年老代物件越來越多,我們就需要啟動Major GC和Full GC(全量回收),來一次大掃除,全面清理年輕代區域和年老代區域。

  3. 持久代

  用於存放靜態檔案,如Java類、方法等。持久代對垃圾回收沒有顯著影響。

1.png

圖4-7 堆記憶體的劃分細節

  ·Minor GC:

  用於清理年輕代區域。Eden區滿了就會觸發一次Minor GC。清理無用物件,將有用物件複製到“Survivor1”、“Survivor2”區中(這兩個區,大小空間也相同,同一時刻Survivor1和Survivor2只有一個在用,一個為空)

  ·Major GC:

  用於清理老年代區域。

  ·Full GC:

  用於清理年輕代、年老代區域。 成本較高,會對系統性能產生影響。

垃圾回收過程:

    1、新建立的物件,絕大多數都會儲存在Eden中,

    2、當Eden滿了(達到一定比例)不能建立新物件,則觸發垃圾回收(GC),將無用物件清理掉,

           然後剩餘物件複製到某個Survivor中,如S1,同時清空Eden區

    3、當Eden區再次滿了,會將S1中的不能清空的物件存到另外一個Survivor中,如S2,

          同時將Eden區中的不能清空的物件,也複製到S1中,保證Eden和S1,均被清空。

    4、重複多次(預設15次)Survivor中沒有被清理的物件,則會複製到老年代Old(Tenured)區中,

    5、當Old區滿了,則會觸發一個一次完整地垃圾回收(FullGC),之前新生代的垃圾回收稱為(minorGC)