天天看點

JVM垃圾回收算法小結

對象生存判斷算法

1、引用計數法

給對象中添加一個引用計數器,每當一個地方引用到這個對象的時候,計數器值就加1,當引用失效時,計數器的值就減1,當計數器值變為0時,便說明該對象不可能再被使用了。

優點:實作簡單,判定效率較高。

缺點:當出現對象之間的互相循環引用時,即兩個類中都存在引用字段分别引用着對方的時候,在回收過程中這時該算法無效。

2、可達性分析算法

為了克服引用計數法的弊端,現在比較主流的實作算法是可達性分析算法。該算法的基本思想是通過一系列的成為“GC Roots”的對象作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鍊。如果在一次的搜尋中,一個對象到GC Roots沒有任何的引用鍊相連,則說明此對象是不可用的。具體如圖所示

JVM垃圾回收算法小結

GC Roots的判定:

  1、虛拟機棧(棧幀中的本地變量表)中引用的對象

  2、方法區中靜态屬性引用的對象

  3、方法區中常量引用的對象

  4、本地方法棧中JNI(即一般說的Native方法)引用的對象

垃圾收集算法:

垃圾收集算法有四種:标記-清除算法、複制算法、标記-整理算法、分代收集算法

JVM垃圾回收算法小結

垃圾收集器

常見的JVM垃圾收集器有七種,具體如下圖所示:  

哪種垃圾回收機制可以将整個堆(新生代、老年代)都回收? 答案是G1

JVM垃圾回收算法小結

 

新生代:

采用"标記-複制"算法進行垃圾回收 ,因為不會有記憶體碎片,且新生代的對象朝生夕死,隻會存活很少的對象,适合8:1:1配置設定空間,不會浪費太多記憶體。

1、記憶體碎片太多可能會導緻,當程式在以後的運作過程中需要配置設定較大對象時無法找到足夠連續的記憶體空間而不得不提前出發另一次垃圾收集動作

2、IBM的專門研究表明,新生代中的對象98%是朝生夕死的,是以并不需要按照1:1的比例來劃分記憶體空間,而是将記憶體分為一塊較大的Eden空間和兩塊較小的Survivor空間,每次使用Eden和其中的一塊Survivor。當回收時,将Eden和Survivor中還存活着的兌現個一次性地拷貝到另外一塊Survivor空間上,最後清理掉Eden和剛才用過的Survivor的空間。HotSpot虛拟機預設Eden和Survivor的大小比例是8:1,也就是每次新生代中可用記憶體空間為整個新生代容量的90%,隻有10%的記憶體是會被浪費的。

JVM垃圾回收算法小結

老年代:

采用"标記-整理"算法進行垃圾回收,因為老年代的對象存活率較高,如果采用"标記-複制"算法需要執行較多的複制操作,且浪費50%的空間。

"标記-整理"算法(壓縮):就是将存活的對象移動到一塊,空出連續的空間

JVM垃圾回收算法小結

CMS:是采用"标記-清理"算法,存在記憶體碎片

G1:是采用"标記-整理"算法

ZGC:

1、和G1一樣将堆劃分為Region作為清理、移動,但是ZGC的Region不是固定大小的,而是動态的建立、銷毀大小不一的Region;

2、沒有G1記錄Region之間的對象引用關系的RememberSet,因為ZGC每次都會對所有的Region進行回收,且不分代。

3、着色指針、讀屏障

參考資料:

http://www.360doc.com/content/12/1219/15/495229_255087879.shtml

https://www.cnblogs.com/zhouyuqin/p/5164060.html

jvm