JVM學習筆記(三)垃圾收集算法

  Java虛擬機JVM垃圾收集算法有四種:標記-清除算法、複製算法、標記-整理算法以及分代收集算法。

標記-清除算法

這是JVM最基礎的垃圾收集算法。如下圖:
這裏寫圖片描述

  該算法分爲兩個階段:“標記”和“清除”。首先標記處所有需要回收的對象,然後統一清除被標記的對象。
  該算法,標記和清除兩個階段的效率不高。此外,回收後會產生大量的不連續的內存碎片,分配較大對象時,無法找到足夠大連續內存,進一步會導致垃圾回收次數的增加。

複製算法

爲了解決標記-清除算法的效率問題,出現了複製算法,如下圖:
這裏寫圖片描述
  該算法的思想是將可用內存按容量劃分爲大小相等的兩塊,每次只使用其中的一塊。當這塊的內存用完了,則將還存活的對象複製到另外一塊內存上去,然後再把剛使用過的內存空間一次清理掉。從而達到了每次垃圾回收時只是針對其中一塊,避免了產生內存碎片等情況。

  該算法的代價是隻是使用了其中一塊的內存,代價有點高。

  隨着研究的不斷髮現,商業虛擬機在該算法中不斷進行優化嘗試。比如在HotSpot虛擬機中,新生代中Eden和Survivor的大小比例爲8::1,因爲新生代的對象需要回收的概率大(對象的生命週期短,存活率低),所以內存的可用率達到了90%(新生代分爲:Eden和兩塊Survivor)。每次都是把Eden和Survivor中存活的對象拷貝到另一塊Survivor中,然後清理掉Eden和Survivor空間。

標記-整理算法

  當複製收集算法面對的回收對象爲存活率較高的情況時,要執行較多的複製操作,效率會變低。爲了提高這些對象垃圾回收效率,充分利用可用內存,標記-整理算法出現了。如下圖:
這裏寫圖片描述

  該算法集成了標記-清除和複製收集算法的優點。第一個階段仍是進行標記,第二個階段是把所有存活的對象都向一端移動,按順序排放,然後直接清理掉端邊界意外的內存。該算法避免了標記-清除的內存碎片問題以及複製算法的空間問題。該算法適合於老年代對象的回收。

分代收集

  這是目前大多數虛擬機採用的垃圾回收算法。基於對象的生命週期劃分爲新生代、老年代以及持久代。比如新生代就採用複製收集算法,而老年代就採用標記-清除或者標記-整理算法。如下圖:
這裏寫圖片描述

  對於分代收集,虛擬機需要區分對象的分配年代,是放在新生代還是否放在老年代?。解決的辦法是:jvm爲每個對象定義了一個對象年齡計數器。如果對象在Eden出生並且經過第一次新生代GC(Minor GC)後仍然存活並且能被Survivor容納,則該對象將被移動到另一塊Survivor空間,並將對象年齡計數器加1。對象在Survivor區中每經歷過一次Minor GC,年齡計數器就加1,當它的年齡達到設定的閾值(默認是15)時,則被移動到老年代中。閾值的設置通過參數-XX:MaxTenuringThreshold設置。

  當然,並不是一定達到閾值才被移動到老年代,爲了適應複雜的情況,動態的判定對象年齡,虛擬機規定:如果Survivor空間中相同年齡的所有對象大小的總和大於Survivor空間的一半,對象的年齡大於或者等於該年齡的對象就可以直接進入老年代,不必等到達到設定的閾值。

原文地址

發佈了113 篇原創文章 · 獲贊 19 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章