05JVM-垃圾收集算法

一、垃圾收集算法

1. 標記-清除

  • 標記-清除算法分兩個階段:標記和清除

  • 首先標記出所有需要回收的對象,在標記完成後統一回收。標記的標準就是利用可達性分析算法

這種算法存在一些問題,首先是遍歷所有的對象,本身這個效率就存在問題,清除標記的對象後,會存在大量不連續的內存碎片,如果程序運行過程中需要分配大的對象時,無法找到足夠多的連續內存時,就會不得不提前觸發垃圾回收動作。

2. 複製算法

  • 爲解決效率問題,複製的垃圾收集算法出現了。原理是這樣的:將內存按容量劃分爲大小相等的兩塊,每次只是用一塊,當這一塊內存用完後,還存活的對象複製到另外一塊。

  • HotSpot 新生代就是採用這種算法,分成Eden區和survivor區,survivor又劃分爲2個區from和to;當新對象分配是先在eden區分配,當一次垃圾回收,eden和survivor中還存活的對象一次性複製到另外一塊survivor中。

  • 劃分爲3塊內容,空間使用率和執行效率來看;內存中基本80%~90%的對象都是“朝生夕死”,所以劃分3快內存空間足夠用於複製存活的對象且節省了空間

複製算法在對象存活率高時就要進行較多的複製操作,效率同樣也會變低,更關鍵的是還會浪費一部分的空間。更何況有極端的情況時,100%對象需要移動,效率就更難保證了

3. 標記-整理

  • 標記清理算法存在內存碎片的問題,要解決內存碎片的問題就需要在當內存對象回收時,將還存活的對象移動到一個區域,這樣空閒的內存空間就會連續。

  • 標記-整理算法就是爲解決這個問題產生的,經過一輪標記後,所有存活的對象移動一端,然後直接清理掉邊界外的內存

4. 總結

HotSpot中,結合複製算法,標記清理,標記整理算法的優點。垃圾收集器使用不同的策略,於是就有了新生代和老年。然後這兩個內存區域採用不同的內存回收算法。

  • 新生代採用複製算法
  • 老年代採用標記整理算法

二、收集算法三個要點

GC 在進行垃圾回收過程中,所有的工作線程都會停止。那麼工作線程如何確定停止的時刻,也就是工作線程停止的標準是什麼

下面3個點明確了工作線程停止的時機:

1. 枚舉根節點

可作爲GC Roots節點的主要有全局引用(常量或者類變量)和執行上下文(棧幀中的本地變量)。

在分析GC Roots引用鏈時,要能確保所有對象凍結在某個時間點,這樣才能確保對象引用的準確性。否則在分析過程中對象引用關係在不斷變化,造成分析引用結果不正確。

要確保正確分析對象引用關係,在枚舉根節點時,必須停止所有的工作線程

2. 安全點

安全點的選定是以“是否具有讓程序長時間執行的特徵”爲標識選定

  • 方法調用
  • 循環跳轉
  • 異常跳轉

等待這些會產生SafePoint,當GC發生時,用戶線程跑到這些最近的安全點時會停頓下來。

兩種方案停頓:
1. 搶先式中斷:GC發生時,把所有的線程中斷,如果發現線程中斷的地方不在安全點上,會讓它回覆,繼續運行到安全點上
2. 主動式中斷:GC發生時,在用戶線程寫一個標誌,各個線程主動輪詢這個標誌,發現中斷標誌爲真就自己中斷掛起。

3. 安全區域

如果程序在sleep或者blocked狀態時,線程無法響應JVM的中斷請求,用戶線程就很難到達安全點。

Safe Region就是用來解決這種情況

安全區域是指在一段代碼片段中,引用關係不會發生變化。

當線程執行到Safe Region中的代碼時,首先會標識自己已經進入Safe Region,這樣當JVM要發起GC時,就不用理會Safe Region狀態的線程了。

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