JVM垃圾回收算法標記清除和複製算法

標記清除算法

當堆中的有效空間被耗盡時,JVM就會中止整個程序(也被稱爲stop the world),而後開始兩項工做.一是: 標記, 而是: 清除

標記

遍歷全部GC Roots,將全部GC Roots可達的對象都標記爲存活對象.

清除

遍歷堆中全部的對象把沒有標記的對象所有清除.
在程序運行期間,當堆中的可用內存被耗盡時,GC線程就會啓動並中止程序,GC線程將存活的對象標記一遍,沒有被標記的對象就是垃圾對象,最後這些垃圾對象會被清除掉,而後從新喚醒應用程序.

程序運行時堆中對象的狀態(默認爲0未標記,1爲標記過),假如堆內存的可用空間被消耗完,那麼GC線程就會啓動,中止掉應用程序,使用根可達性算法進行搜索標記.算法

image-20201101144201836

被標記後的對象狀態spa

image-20201101144531448

使用根可達性算法,全部GC Roots可達的對象都被標記爲存活對象,此時已經完成了第一階段的工做.接下來執行清除操做,執行完清除操做,堆中對象的狀態.線程

image-20201101162751111

沒有標記的對象被清除,被標記的對象會被留下,標誌爲被置爲0,應用程序被喚醒.code

標記清除的優勢是算法簡單,缺點以下:對象

1.效率低下,須要遍歷整個堆.進行GC的時候須要中止應用程序
2.垃圾回收後的內存空間是不連續的,由於垃圾對象的分佈很隨意,那麼清除後的內存會不連續. 爲了解決這個問題,JVM不得不維護一個空閒鏈表,又會致使額外的開銷.blog

複製算法

複製算法使用了兩塊同等大小的內存空間,每次只用一塊,垃圾回收的時候,把存活的對象直接另一塊內存,而後剩餘的垃圾對象所有一次性清除.好處是複製存活對象的時候就不用考慮內存碎片.惟一的缺點就是內存利用率只有50%.

img

如今的虛擬機通常都用複製算法回收新生代,IBM的研究發現,新生代中的對象98%都是朝生夕死,因此並不須要1:1分配對象,而是將內存分爲一個大的Eden和兩塊小的Survivor空間,每次只使用Eden和一塊Survivor. 當進行垃圾回收時,將存活對象一次性複製到一塊Survivor空間,最後清除掉Eden和使用過的Survivor空間. HotSpot虛擬機Eden:Survivor=8:1,也就新生代可用的內存達到90%,只會有10%的浪費.固然98%的對象可被回收只是通常的場景,並無辦法保證每次Survivor都能存放的下存活對象,若Survivor空間不夠時,須要依靠老年代進行分配擔保.

image-20201101173454757

from ,to爲Survivor區。內存

相關文章
相關標籤/搜索