GC回收算法

GC就是Garbage Collection,垃圾收集,GC的對象是Java堆和方法區(永久),所謂的垃圾是指在系統運行期間產生的一些無用的對象,而這些對象佔有一定的內存空間,如果長期不釋放就很有可能導致OOM(內存溢出)。

標記-清除算法

標記清除算法是最基礎的垃圾收集算法,分爲標記和清除兩個階段。首先會標記出所有需要回收的對象,在標記完成後統一對需要回收的對象進行回收。如下圖:

在這裏插入圖片描述

在上圖中,黑色代表需要被回收的,灰色代表存活的對象,白色表示未使用的對象。黑色的部分是要標記的部分,回收完成後變成白色部分。這樣一來,我們可以總結出標記清除算法的兩個缺點:

1.標記和清除這兩個過程的效率都非常低
2.產生不連續的內存碎片,內存碎片過多會導致以後在給一個較大的對象分配內存時無法找到一塊連續的內存空間而不得不提前觸發另一次垃圾收集。

複製算法(新生代回收算法)

複製算法是爲了解決標記清除算法的效率低的問題,它將可用內存分爲大小相等的兩塊區域,每次只使用一塊區域,當使用的這塊內存需要垃圾回收的時候,會將這塊區域還存活的對象複製到另一塊,再將這一塊使用過的對象一次性一塊清理。這樣就不需要考慮內存碎片等複雜的情況,因爲每次都是對整個半區進行回收的。

在這裏插入圖片描述
如上圖所示,藍色代表內存,分爲左右兩個大小相等的內存。
現在的商用虛擬機包括hotspot都使用這種算法回收新生代

新生代中98%的對象都是"朝生夕死"的,所以並不需要按照1 : 1的比例來劃分內存空間,而是將內存(新生代內存)分爲一塊較大的Eden(伊甸園)空間和兩塊較小的Survivor(倖存者)空間,每次使用Eden和其中一Survivor(一個Survivor區域一個稱爲From區,另一個稱爲To區域)。當回收時,將Eden和Survivor中還存活的對象一次性複製到另一塊Survivor空間上,最後清理掉Eden和剛纔用過的Survivor空間。

HotSpot默認Eden與Survivor的大小比例是8 : 1,也就是說Eden:Survivor From : Survivor To = 8:1:1。所以每次
新生代可用內存空間爲整個新生代容量的90%,而剩下的10%用來存放回收後存活的對象。
HotSpot實現的複製算法流程如下:

  1. 當Eden區滿的時候,會觸發第一次Minor gc,把還活着的對象拷貝到Survivor From區;當Eden區再次觸
    發Minor gc的時候,會掃描Eden區和From區域,對兩個區域進行垃圾回收,經過這次回收後還存活的對象,
    則直接複製到To區域,並將Eden和From區域清空。
  2. 當後續Eden又發生Minor gc的時候,會對Eden和To區域進行垃圾回收,存活的對象複製到From區域,並將
    Eden和To區域清空。
  3. 部分對象會在From和To區域中複製來複制去,如此交換15次(由JVM參數MaxTenuringThreshold決定,這
    個參數默認是15),最終如果還是存活,就存入到老年代

在這裏插入圖片描述

標記-整理算法(老年代回收算法)

複製算法一般當對象存活比較高的時候會進行較多的複製,這樣效率就會變得很低,所以在老年代一般不使用這種算法。而是用標記整理算法。標記整理算法和標記清除算法前面的步驟一樣,但後續不是直接對可回收的對象進行清理,而是讓所有存活的對象都向一端移動,然後將端以外邊界的內存都清理掉。如圖:

在這裏插入圖片描述

分代收集算法

當前的JVM使用的都是分代收集算法,根據對象的存活週期的不同劃分爲幾個塊,一般是把Java堆分爲新生代和老年代,新生代每次回收都有大批的對象死去,只有少量的對象存活,因此使用複製回收算法。老年代存活時間比較久,但是沒有額外的空間對它分配擔保,所以就必須採用標記清除或者標記整理算法。

面試題

請問了解Minor GC和Full GC麼,這兩種GC有什麼不一樣嗎?

  1. Minor GC又稱爲新生代GC : 指的是發生在新生代的垃圾收集。因爲Java對象大多都具備朝生夕滅的特
    性,因此Minor GC(採用複製算法)非常頻繁,一般回收速度也比較快。
  2. Full GC 又稱爲 老年代GC或者Major GC : 指發生在老年代的垃圾收集。出現了Major GC,經常會伴隨
    至少一次的Minor GC(並非絕對,在Parallel Scavenge收集器中就有直接進行Full GC的策略選擇過程)。
    Major GC的速度一般會比Minor GC慢10倍以上。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章