天天看點

【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

在前面我們了解了虛拟機如何判斷對象可回收,接下來我們了解Java虛拟機垃圾收集的一些理論和算法。

1、分代收集理論

分代收集理論,是基于程式運作對象存活數量和對象年齡之間關系的一套經驗法則。

【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

它建立在兩個分代假說之上:

  • 弱分代假說(Weak Generational Hypothesis):絕大多數對象都是朝生夕滅的。
  • 強分代假說(Strong Generational Hypothesis):熬過越多次垃圾收集過程的對象就越難以消亡。

用通俗的話總結:大部分污漬很容易擦幹淨,多次擦都沒擦幹淨的無責越來越難擦幹淨。

基于這個理論,收集器将Java堆劃分出不同的區域,然後将回收對象按照年齡配置設定到不同的區域存儲。

具體來講,就是把Java堆劃分為新生代 (Young Generation)和老年代(Old Generation)兩個區域,新生代存放存活時間短的對象,而每次回收後存活的少量對象,将會逐漸晉升到老年代中存放。

【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

對于新生代的對象,可以隻關注如何保留少量存活而不是去标記那些大量将要被回收的對象;

對于老年代,可以降低垃圾收集頻率,同時更加關注那些要消亡的對象。

為了降低垃圾回收的代價,在新生代和老年代采用了不同的垃圾收集算法。

基于分代,産生了一些垃圾收集的類型劃分:
  • 部分收集(Partial GC):指目标不是完整收集整個Java堆的垃圾收集,其中又分為:
    • 新生代收集(Minor GC/Young GC):指目标隻是新生代的垃圾收集。
    • 老年代收集(Major GC/Old GC):指目标隻是老年代的垃圾收集。目前隻有CMS收集器會有單獨收集老年代的行為。
    • 混合收集(Mixed GC):指目标是收集整個新生代以及部分老年代的垃圾收集。目前隻有G1收集器會有這種行為。
  • 整堆收集(Full GC):收集整個Java堆和方法區的垃圾收集。

2、垃圾收集算法

2.1、标記-清除算法

見名知義,

标記-清除

(Mark-Sweep)算法分為兩個階段:

  • 标記 : 标記出所有需要回收的對象
  • 清除:回收所有被标記的對象
【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

标記-清除算法比較基礎,但是主要存在兩個缺點:

  • 執行效率不穩定,如果Java堆中包含大量對象,而且其中大部分是需要被回收的,這時必須進行大量标記和清除的動作,導緻标記和清除兩個過程的執行效率都随對象數量增長而降低。
  • 記憶體空間的碎片化問題,标記、清除之後會産生大量不連續的記憶體碎片,空間碎片太多可能會導緻當以後在程式運作過程中需要配置設定較大對象時無法找到足夠的連續記憶體而不得不提前觸發另一次垃圾收集動作。

标記-清除算法主要用于老年代,因為老年代可回收的對象比較少。

2.2、标記-複制算法

标記-複制算法解決了标記-清除算法面對大量可回收對象時執行效率低的問題。

過程也比較簡單:将可用記憶體按容量劃分為大小相等的兩塊,每次隻使用其中的一塊。當這一塊的記憶體用完了,就将還存活着的對象複制到另外一塊上面,然後再把已使用過的記憶體空間一次清理掉。

【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

這種算法存在一個明顯的缺點:一部分空間沒有使用,存在空間的浪費。

新生代垃圾收集主要采用這種算法,因為新生代的存活對象比較少,每次複制的隻是少量的存活對象。

一般虛拟機的具體實作不會采用1:1的比例劃分,以HotSpot為例,HotSpot虛拟機将記憶體分為一塊較大的Eden空間和兩塊較小的 Survivor空間,每次配置設定記憶體隻使用Eden和其中一塊Survivor。發生垃圾搜集時,将Eden和Survivor中仍然存活的對象一次性複制到另外一塊Survivor空間上,然後直接清理掉Eden和已用過的那塊Survivor空間。預設Eden和Survivor的大小比例是8∶1。

【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

2.3、标記-整理算法

為了降低記憶體的消耗,引入一種針對性的算法:

标記-整理

(Mark-Compact)算法。

其中的标記過程仍然與“标記-清除”算法一樣,但後續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向記憶體空間一端移動,然後直接清理掉邊界以外的記憶體。

【JVM進階之路】六:垃圾收集理論和算法1、分代收集理論2、垃圾收集算法

标記-整理算法主要用于老年代,在老年代這種大量對象存活的區域,移動對象是個很大的負擔,而且這種對象移動操作必須全程暫停使用者應用程式(Stop The World)才能進行。