1. 程式人生 > >G1 垃圾收集器

G1 垃圾收集器

一,垃圾回收

  垃圾回收就是回收記憶體中不再使用的物件。

  步驟有2步:

    1. 查詢記憶體中不再使用的物件

      (1)引用計數法:有一個缺點,不能檢測到環的存在

      (2)根搜尋演算法:通過一系列名為“GC Roots”的物件作為起始點,當一個物件到GC Roots沒有任何引用鏈相連時,則證明此物件是不可用的

    2.釋放這些物件佔用的記憶體

        (1) 標記-複製 :它將可用記憶體容量劃分為大小相等的兩塊,每次只使用其中的一塊。當這一塊用完之後,就將還存活的物件複製到另外一塊上面,然後在把已使用過的記憶體空間一次理掉。它的優點是實現簡單,效率高,不會存在記憶體碎片。缺點就是需要2倍的記憶體來管理。

      (2) 標記-清理:清除演算法分為“標記”和“清除”兩個階段:首先標記出需要回收的物件,標記完成之後統一清除物件。它的優點是效率高,缺點是容易產生記憶體碎片。

        (3) 標記-整理:標記操作和“標記-清理”演算法一致,後續操作不只是直接清理物件,而是在清理無用物件完成後讓所有 存活的物件都向一端移動,並更新引用其物件的指標。因為要移動物件,所以它的效率要比“標記-清理”效率低,但是不會產生記憶體碎片。

 

      新生代和老生代:

    由於物件的存活時間有長有短,所以對於存活時間長的物件,減少被gc的次數可以避免不必要的開銷。這樣我們就把記憶體分成新生代和老年代,新生代存放剛建立的和存活時間比較短的物件,老年代存放存活時間比較長的物件。這樣每次僅僅清理年輕代,老年代僅在必要時時再做清理可以極大的提高GC效率,節省GC時間。

  

  java垃圾收集器的歷史:

    1. Serial(序列)收集器

    2. Parallel(並行)收集器

    3. CMS(併發)收集器

    4. G1(併發)收集器

 

二,瞭解G1

  oracle官方計劃在jdk9中將G1變成預設的垃圾收集器,以替代CMS。

  G1的設計原則就是簡單可行的效能調休。將新生代,老生代的物理空間劃分取消了。

  

  細節:

G1演算法將堆劃分為若干個區域(Region),它仍然屬於分代收集器。不過,這些區域的一部分包含新生代,新生代的垃圾收集依然採用暫停所有應用執行緒的方式,將存活物件拷貝到老年代或者Survivor空間。老年代也分成很多區域,G1收集器通過將物件從一個區域複製到另外一個區域,完成了清理工作。這就意味著,在正常的處理過程中,G1完成了堆的壓縮(至少是部分堆的壓縮),這樣也就不會有cms記憶體碎片問題的存在了。

在G1中,還有一種特殊的區域,叫Humongous區域。 如果一個物件佔用的空間超過了分割槽容量50%以上,G1收集器就認為這是一個巨型物件。這些巨型物件,預設直接會被分配在年老代,但是如果它是一個短期存在的巨型物件,就會對垃圾收集器造成負面影響。為了解決這個問題,G1劃分了一個Humongous區,它用來專門存放巨型物件。如果一個H區裝不下一個巨型物件,那麼G1會尋找連續的H分割槽來儲存。為了能找到連續的H區,有時候不得不啟動Full GC。

PS:在java 8中,持久代也移動到了普通的堆記憶體空間中,改為元空間。

 

     最後,G1提供了兩種GC模式,Young GC和Mixed GC,兩種都是Stop The World(STW)的。