jvm 的垃圾回收算法
1.標記-清除算法
標記出所有需要回收的對象,在標記完成后,統一回收掉所有被標記的對象,也可以反過來,標記出所有存活的對象,在標記完成后,統一回收所有未被標記的對象,標記過程就是對象是否屬于垃圾的判定過程,基于可達性分析算法判斷對象是否可以回收;
標記后,對所有被標記的對象進行回收;
缺點:
等待被回收對象的“標記”過程在上文已經提到過,如果在被標記后直接對對象進行清除,會帶來另一個新的問題——內存碎片化。如果下次有比較大的對象實例需要在堆上分配較大的內存空間時,可能會出現無法找到足夠的連續內存而不得不再次觸發垃圾回收。
2.復制算法(Java堆中新生代的垃圾回收算法)
復制算法是標記-復制算法的簡稱,將可用內存按容量分為大小相等的兩塊,每次只使用其中一塊,當這一塊的內存用完了,就將還存活的對象復制到另外一塊內存上,然后再把已使用過的內存空間一次清理掉;
此GC算法實際上解決了標記-清除算法帶來的“內存碎片化”問題。首先還是先標記處待回收內存和不用回收的內存,下一步將不用回收的內存復制到新的內存區域,這樣舊的內存區域就可以全部回收,而新的內存區域則是連續的。它的缺點就是會損失掉部分系統內存,因為你總要騰出一部分內存用于復制。
新的對象實例被創建的時候通常在Eden空間,發生在Eden空間上的GC稱為Minor GC,當在新生代發生一次GC后,會將Eden和其中一個Survivor空間的內存復制到另外一個Survivor中,如果反復幾次有對象一直存活,此時內存對象將會被移至老年代。可以看到新生代中Eden占了大部分,而兩個Survivor實際上占了很小一部分。這是因為大部分的對象被創建過后很快就會被GC(這里也許運用了是二八原則)。
3.標記-壓縮算法(或稱為標記-整理算法,Java堆中老年代的垃圾回收算法)
對于新生代,大部分對象都不會存活,所以在新生代中使用復制算法較為高效,而對于老年代來講,大部分對象可能會繼續存活下去,如果此時還是利用復制算法,效率則會降低。標記-壓縮算法首先還是“標記”,標記過后,將不用回收的內存對象壓縮到內存一端,此時即可直接清除邊界處的內存,這樣就能避免復制算法帶來的效率問題,同時也能避免內存碎片化的問題。老年代的垃圾回收稱為“Major GC”。
優點:
1、不會像復制算法那樣劃分兩個區域,提高了空間利用率;
2、不會產生不連續的內存碎片;
缺點:效率問題,除了像標記-清除算法的標記過程外,還多了一步整理過程,效率變低;
4、分代收集算法
在一般虛擬機的垃圾收集都是采用“ 分代收集 ”算法;
根據對象存活周期的不同將內存劃分為幾塊,一般把java堆分為新生代和老年代,JVM根據各個年代的特點采用不同的收集算法;
新生代中,每次進行垃圾回收都會發現大量對象死去,只有少量存活,因此采用復制算法,只需要付出少量存活對象的復制成本就可以完成收集;
老年代中,因為對象存活率較高,采用標記-清理、標記-整理算法來進行回收;
總結
以上是生活随笔為你收集整理的jvm 的垃圾回收算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM内存相关的核心参数?
- 下一篇: JVM怎么判断对象是否存活