《深入理解Java虛擬機》(二)--垃圾收集器與內存分配策略(2)

垃圾收集算法:

1/1 標記-清除算法(Mark-Sweep):

最基礎的垃圾回收算法,它分爲兩個階段,標記和清除:首先它會標記出所有需要回收的對象,在標記完成之後統一回收所有被標記對象,它的標記過程之前已經提到了。

缺點:

1、效率低:它的標記和清除兩個過程效率都不高。
2、空間問題:因爲標記和清除之後會產生大量的不連續的片段,空間碎片太多可能會導致以後需要分配大對象的過程中,由於無法找到足夠的連續內存而不得不提前觸發一次垃圾收集。
具體過程如下:


12350543-3e66997808c40c25.png
標記-清除算法的具體過程

1/2 複製算法(Copying):

複製算法是將可用的內存按照容量大小分爲相等的兩塊,每次只使用其中的一塊,當這一塊的內存用完了,就將上面還存活的對象複製到另一塊沒用過的內存中,然後清理之前使用過的內存。

優點:

這樣的算法使得每次都對整個半區進行內存回收,內存分配時也不用考慮內存碎片等複雜情況,只要移動堆頂指針,按順序分配內存即可,實現簡單,運行高效。

缺點:

這種算法的代價是將能夠使用的內存縮小爲原來的一半,浪費的資源太多了。
具體的過程如下:


12350543-e7f74130af5c75c4.png
複製算法的具體執行過程
新生代和老年代:

新生代指的是頻繁出生和死亡的對象區域,相反老年代的對象都比較穩定。

改進:

其實新生代中的大部分對象是“朝生夕死”,生命很短,也就是說存活的對象很少,所以並不需要按照1:1的比例去分配內存空間,在HotSpot虛擬機中,是將一塊內存分爲一塊較大的內存空間Eden和兩塊較小的空間Survivor,他們的默認比例是8:1:1,每次使用的是Eden和其中的一塊Survivor。當回收時,將Eden和那塊Survivor中還存活的對象(因爲是新生代,所以很少)全部複製到另一塊Survivor中,最後清理掉剛纔所使用的Eden和Survivor,這樣每次只有10%會被“浪費掉”,解決了浪費資源太多的問題。雖然新生代中的存活對象很少,但有的時候還是會超過那10%的內存空間,當那塊Survivor空間不夠用的時候,這些對象將直接通過分配擔保機制進入老年代。

1/3 標記-整理算法(Mark-Compact):

如果在對象存活情況較多的時候(老年代中),顯然,複製收集算法的效率會很低,爲了應對這種情況,老年代中一般選用標記-整理算法。
標記整理算法的標記過程與標記清除算法一樣,但是後續的步驟是將存活的對象向着內部的邊界(比如上邊)移動,也就是說移動完之後,存活的對象都緊挨着,然後直接清除掉存活對象以外的對象。
具體過程如下:


12350543-90195b12fb53e98f.png
標記-整理算法的具體過程

1/4 分代收集算法:

分代收集算法並不是一種特定的算法,它是根據對象存活週期的不同將內存劃分爲幾塊,一般是將Java堆分成新生代和老年代,這樣根據各個年代的特點選擇最適合的垃圾收集算法,新生代中對象頻繁的創建和死去,就使用複製算法,老年代的對象比較穩定,就使用標記-清除或者標記-整理算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章