1) 標記/清除算法是怎么來的?
我們在程序運行期間如果想進行垃圾回收,就必須讓GC線程與程序當中的線程互相配合,才能在不影響程序運行的前提下,順利的將垃圾進行回收。
為了達到這個目的,標記/清除算法就應運而生了。
2)標記/清除算法的過程
它的做法是當堆中的有效內存空間(available memory)被耗盡的時候,就會讓整個程序stop the world,然后進行兩項工作,第一是標記,第二是清除
標記: 標記的過程其實就是,遍歷所有的GC Roots,然后將所有的 GC Roots可達的對象標記為存活的對象。
清除: 清楚的過程將遍歷堆中所有的對象中沒有標記的對象全部清除掉
當程序運行期間,若可以使用的內存被耗盡的時候,GC線程就會被觸發並將程序暫停,隨后將依舊存活的對象標記一遍,最終再將堆中所有沒有被標記的對象全部清除掉,接下來便讓程序恢復運行
3)為什么要stop the world
這個其實也不難理解,舉個最簡單的例子,假設我們的程序與GC線程是一起運行的,各位試想這樣一種場景。
假設我們剛標記完的那個對象,暫且記為A,結果此時在程序當中又new了一個新對象B,且A對象可以到達B對象。但是由於此時A對象已經標記結束,B對象此時的標記位依然是0,因為它錯過了標記階段。因此當接下來輪到清除階段的時候,新對象B將會被苦逼的清除掉。如此一來,不難想象結果,GC線程將會導致程序無法正常工作。
上面的結果當然令人無法接受,我們剛new了一個對象,結果經過一次GC,忽然變成null了,這還怎么玩?
4)標記/清理算法的缺點
1、首先,它的缺點就是效率比較低(遞歸與全堆對象遍歷),而且在進行GC的時候,需要停止應用程序,這會導致用戶體驗非常差勁,尤其對於交互式的應用程序來說簡直是無法接受。試想一下,如果你玩一個網站,這個網站一個小時就掛五分鍾,你還玩嗎?
2、第二點主要的缺點,則是這種方式清理出來的空閑內存是不連續的,這點不難理解,我們的死亡對象都是隨即的出現在內存的各個角落的,現在把它們清除之后,內存的布局自然會亂七八糟。而為了應付這一點,JVM就不得不維持一個內存的空閑列表,這又是一種開銷。而且在分配數組對象的時候,尋找連續的內存空間會不太好找。
看完它的缺點估計有的猿友要忍不住吐糟了,“這么說這個算法根本沒法用嘛,那LZ還介紹這么個玩意干什么。”
猿友們莫要着急,一個算法有缺點,高人們自然會想盡辦法去完善它的。而接下來我們要介紹的兩種算法,皆是在標記/清除算法的基礎上優化而產生的。
學習並轉載自 https://www.cnblogs.com/Leo_wl/p/3269590.html