[jvm解析系列][四]Java的垃圾回收(二)垃圾收集算法,內存分配和回收策略

上回說到如何鑑別一個垃圾。

這回咱們講講怎麼收集垃圾收集垃圾有幾種算法如下:

1、標記-清除算法

這個算法最爲基礎,我們先講算法再說優缺點。

實現過程:

標記出所有需要回收的對象,當標記完成後統一回收。圖解如下:

優缺點:

可能畫出來圖的時候大家都發現了,這個算法有一個很明顯的問題,那就是大量的不連續的內存碎片,這樣的內存碎片遇到大對象分配的時候很可能遇到內存不足的 情況,當然出了這個情況以外還有一種問題就效率太低(可以對比之後的算法)。

2、複製算法

實現:把內存劃分爲大小相等的兩塊,當GC的時候,就把其中一塊複製到另一塊上,然後直接清理掉原本的那一半內存。

優缺點

這種算法要比標記清除算法效率高並且沒有內存碎片,但是這樣會浪費一半內存而且如果存貨較多對象,複製效率也很低。

修正與應用:

現在商業虛擬機大多都採用這種方式回收新生代,但是不回劃一半內存那麼大。它們把內存氛圍Eden空間(80%)和兩塊Survivor空間(10%+10%),每次GC時, 從Eden和一個survivor區裏複製活着的對象到另一個survivor裏,因爲新生代 GC頻繁且效率高,所以一半清除後的對象一個survivor基本可以存下,但是如果空間不夠 用,就會引起老年代的分配擔保(在本章稍後講解)。

3、標記-整理算法

實現:

讓所有存活的對象向前端移動,最後清除後面的內存

優缺點

效率高於標記-清除算法,而且可以保證所有的內存都可以使用

應用:

這種算法可以有效的用在老年代中,因爲老年代gc不頻繁而且每次效率不高。

我們瞭解到了怎麼清理內存之後,這在之前還有一個問題,分配對象的規則是什麼呢

1、分配對象

我們用流程圖來講解:

1我們可以看出來一個對象在分配的時候先要看看Eden區是否可以裝得下(或者設置了PretenureSizeThreshold參數,根據參數來判斷)

2、如果裝不下就直接分配到老年區

3、如果分配的下又會查詢Eden空間是否是充足

4、如果Eden剩餘可用內存充足就把對象放在了Eden區域

5、如果Eden不充足的話就會引起MinorGC(新生代GC,新生代GC效率較高大概是FullGC(老年代GC)的十倍),如果發現Eden中的對象不足以放在survivor中就 會直接放在老年代裏,然後分配對象到新生代。

2、長期存活對象轉入老年代

圖解:

特殊情況

虛擬機中並沒有嚴格的遵守必須年齡>=MaxTenuringThreshold才能轉到老年代,如果Survivor空間中相同年齡所有對象大小的綜合大雨Survivor空間的一半,年 齡>=它們的也可直接轉到老年代。

3、空間分配擔保

實現:

在MinorGC之前每次都會查看老年代的最大連續可用空間是不是大於新生代所有總對象總空間,如果大於的話說明新生代可以轉入老年代,如果空間不足保證所有的 survivor區域裏的話說明不安全,因爲很有可能MinorGC後晉升老年代,老年代根本存不下,所以這個時候要查看是否設置了允許冒這個險,(參數 HandlerPromotionFailure)除了檢測參數外還要查看是否大於以往晉升對象的平均值,都允許的話就開始冒險。如果不允許就先FullGC。

冒險:嘗試把MinorGC後剩餘的對象放入老年代,如果成功最好,省了FullGC,如果失敗只能跑一次FullGC了,時間花銷最大。

圖解如下:

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