JVM中垃圾回收相关算法 - 值得了解一下的,因为早晚得了解
JVM中垃圾回收相關(guān)算法 - 我想是值得你了解一下的,因為早晚得了解。😁
概要:當(dāng)成功區(qū)分出內(nèi)存中存活對象和死亡對象后,GC接下來的任務(wù)就是執(zhí)行垃圾回收,釋放掉無用對象所占用的內(nèi)存空間,以便有足夠的可用內(nèi)存空間為新對象分配內(nèi)存。目前在JVM中比較常見的三種垃圾收集算法是:標(biāo)記一清除算法(Mark-Sweep)復(fù)制算法(copying)標(biāo)記-壓縮算法(Mark-Compact)
地點:湖南省永州市藍(lán)山縣舜河村
作者:用心笑*😀
JVM 垃圾回收相關(guān)算法
- 一、標(biāo)記-清除算法
- 1)標(biāo)記:
- 2)清除:
- 二、標(biāo)記-復(fù)制算法
- 2.1、概述:
- 2.2、圖示
- 2.3、優(yōu)缺點
- 優(yōu)點
- 缺點
- 2.4、注意
- 三、標(biāo)記-整理算法(標(biāo)記-壓縮算法)
- 3.1、概述
- 3.2、標(biāo)記-清除與標(biāo)記整理算法區(qū)別
- 3.3、優(yōu)缺點
- 3.4、小結(jié)
- 四、自言自語
一、標(biāo)記-清除算法
標(biāo)記-清掃式垃圾回收器是一種直接的全面停頓算法。簡單的說,它們找出所有不可達(dá)的對象,并將它們放入空閑列表Free。
1)標(biāo)記:
標(biāo)記的過程其實就是,遍歷所有的GC Roots,然后將所有GC Roots可達(dá)的對象標(biāo)記為存活的對象。
如下圖:
2)清除:
清除的時候?qū)⒈闅v堆中所有的對象,將沒有標(biāo)記到的對象全部給清理掉
這里所謂的清除并不是真的置空,而是把需要清除的對象地址保存在空閑的地址列表里。下次有新對象需要加載時,判斷垃圾的位置空間是否夠,如果夠,就存放覆蓋原有的地址。
- 如果內(nèi)存規(guī)整
- 采用指針碰撞的方式進(jìn)行內(nèi)存分配
- 如果內(nèi)存不規(guī)整
- 虛擬機需要維護(hù)一個列表
- 空閑列表分配
優(yōu)點:優(yōu)點就是簡單理解,容易實現(xiàn)。內(nèi)存消耗較小。
缺點:1)不管標(biāo)記還是沒有標(biāo)記,都需要進(jìn)行整體掃描一遍,效率低;2) 進(jìn)行GC 時,會停止用戶程序,并且時間開銷大,對用戶體驗較差;3)垃圾回收清理出來的空間內(nèi)存,內(nèi)存可能是不連續(xù)的,這就可能會產(chǎn)生內(nèi)碎片(操作系統(tǒng)方面知識),就需要再維護(hù)一個空列表。
二、標(biāo)記-復(fù)制算法
2.1、概述:
為了解決標(biāo)記 - 清除算法在垃圾收集效率方而的缺陷M.L.Minsky于1963 年發(fā)表了著名的論文, “ 使用雙存儲區(qū)的Lisp語言垃圾收集器CA LISP Garbage CoIIector Algorithm Using SeriaI Secondary Storage 。M.L.Minsky 在該論文中描述的算法被人們稱為復(fù)制(copying) 算法, 它也被M.L.Minsky 本人成功地引入到了Lisp語言的一個實現(xiàn)版本中。
GC復(fù)制算法原理是把內(nèi)存分為兩個空間一個是From空間,一個是To空間,對象一開始只在From空間分配,To空間是空閑的。GC時把存活的對象從From空間復(fù)制粘貼到To空間,之后把To空間變成新的From空間,原來的From空間變成To空間。回收前后對比下圖所示
2.2、圖示
應(yīng)用場景:目前JVM大都使用在新生代的垃圾回收中。
2.3、優(yōu)缺點
對于任意的GC算法我們都可以從吞吐量(GC延遲),內(nèi)存的分配效率,內(nèi)存碎片化,堆的使用效率這個幾個方面評估。
優(yōu)點
-
GC復(fù)制算法只搜索并復(fù)制存活的對象,少了訪問整堆和構(gòu)造空閑鏈表的操作能夠在短時間內(nèi)完成GC。換言之,GC復(fù)制的吞吐量要比標(biāo)記-清除要優(yōu)秀,并且堆越大這種差距越明顯。
-
內(nèi)存的分配效率:GC復(fù)制算法不使用空閑鏈表,因為分塊本身就是一個連續(xù)的空間。只要新建的對象不超過剩余空間的大小,只需要移動指針即可~。所以GC復(fù)制算法的分配效率非常的高效。
-
復(fù)制過去以后保證空間的連續(xù)性,不會出現(xiàn)“碎片”問題。
缺點
- 此算法的缺點也是很明顯的,就是需要兩倍的內(nèi)存空間。
- 復(fù)制而不是移動,意味著GC需要維護(hù)兩塊內(nèi)存之間對象引用關(guān)系,不管是內(nèi)存占用或者時間開銷也不小
2.4、注意
復(fù)制算法還有一個情況:如果系統(tǒng)中的垃圾對象很多,復(fù)制算法需要復(fù)制的存活對象數(shù)量并不會太大,或者說非常低才行(老年代大量的對象存活,那么復(fù)制的對象將會有很多,效率會很低),所以復(fù)制算法大都是應(yīng)用在新生代中的垃圾回收。
三、標(biāo)記-整理算法(標(biāo)記-壓縮算法)
3.1、概述
復(fù)制算法的高效性是建立在存活對象少、垃圾對象多的前提下的,這種情況在新生代經(jīng)常發(fā)生,老年代很難出現(xiàn)這種情況。
標(biāo)記一清除算法的確可以應(yīng)用在老年代中,但是該算法不僅執(zhí)行效率低下,而且在執(zhí)行完內(nèi)存回收后還會產(chǎn)生內(nèi)存碎片,所以JVM的設(shè)計者認(rèn)為前兩種都有問題,即提出了第三種垃圾收集算法:標(biāo)記-整理算法,可以說是整合了前兩種的優(yōu)勢。
前面標(biāo)記部分同標(biāo)記清除部分,不同的地方在于,標(biāo)記清除中只是把可回收的對象進(jìn)行垃圾回收,不會對剩余的內(nèi)存空間進(jìn)行整理,而標(biāo)記整理則會對存活的對象進(jìn)行整理,截圖對比如下所示:
3.2、標(biāo)記-清除與標(biāo)記整理算法區(qū)別
標(biāo)記-壓縮算法的最終效果等同于標(biāo)記-清除算法執(zhí)行完成后,再進(jìn)行一次內(nèi)存碎片整理,因此,也可以把它稱為標(biāo)記-清除-壓縮(Mark-Sweep-Compact)算法。
二者的本質(zhì)差異在于標(biāo)記-清除算法是一種非移動式的回收算法,標(biāo)記-壓縮是移動式的。是否移動回收后的存活對象是一項優(yōu)缺點并存的風(fēng)險決策。可以看到,標(biāo)記的存活對象將會被整理,按照內(nèi)存地址依次排列,而未被標(biāo)記的內(nèi)存會被清理掉。如此一來,當(dāng)我們需要給新對象分配內(nèi)存時,JVM只需要持有一個內(nèi)存的起始地址即可,這比維護(hù)一個空閑列表顯然少了許多開銷。
3.3、優(yōu)缺點
優(yōu)點: 則是一定程度上解決了前兩種算法的缺陷,1)消除了標(biāo)記-清除算法當(dāng)中,內(nèi)存區(qū)域分散的缺點;2)不用像復(fù)制算法一樣,內(nèi)存減半的高額代價。
缺點:
1)從效率上講,是不如復(fù)制算法的。
2)移動對象的同時,如果對象被其他對象引用,則還需要調(diào)整引用的地址
3)移動過程中,需要全程暫停用戶應(yīng)用程序。
3.4、小結(jié)
| 速率 | 中等 | 最慢 | 最快 |
| 空間開銷 | 少(但會堆積碎片) | 少(不堆積碎片) | 通常需要活對象的2倍空間(不堆積碎片) |
| 移動對象 | 否 | 是 | 是 |
結(jié)論:沒有最好的算法,只有最合適的算法。(不然那還有這么多算法的存在勒)
堆部分中年輕代是是使用標(biāo)記-復(fù)制算法進(jìn)行垃圾回收,主要是因為年輕代里的對象存活時間比較短,大都朝生夕死,一次可以清除大部分對象,這樣只需要把少數(shù)對象移到另一塊內(nèi)存中去,效率很高。
但是在老年代中,就不一樣了,老年代老年代,你一聽就知道這里面對象的存活時間很長,而且大多數(shù)對象都會活很久,如果使用復(fù)制算法,每次清除的對象很少,需要移動的對象很多,效率很低。那么使用標(biāo)記-整理或者標(biāo)記-清除更加合適,效率也會比較高。
四、自言自語
每天的生活,慢慢變的充實,未來很長,我們一起努力!!!
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的JVM中垃圾回收相关算法 - 值得了解一下的,因为早晚得了解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM 垃圾回收算法 -可达性分析算法!
- 下一篇: JUC系列(二)回顾Synchroniz