JVM中四種GC算法案例詳解
介紹
程序在運行過程中,會產(chǎn)生大量的內(nèi)存垃圾(一些沒有引用指向的內(nèi)存對象都屬于內(nèi)存垃圾,因為這些對象已經(jīng)無法訪問,程序用不了它們了,對程序而言它們已經(jīng)死亡),為了確保程序運行時的性能,java虛擬機在程序運行的過程中不斷地進行自動的垃圾回收(GC)。關(guān)于 JVM 的 GC 算法主要有下面四種:
引用計數(shù)算法(Reference counting)
算法思想:
每個對象在創(chuàng)建的時候,就給這個對象綁定一個計數(shù)器。每當(dāng)有一個引用指向該對象時,計數(shù)器加一;每當(dāng)有一個指向它的引用被刪除時,計數(shù)器減一。這樣,當(dāng)沒有引用指向該對象時,該對象死亡,計數(shù)器為0,這時就應(yīng)該對這個對象進行垃圾回收操作。
核心思想:
為每個對象額外存儲一個計數(shù)器 RC ,根據(jù) RC 的值來判斷對象是否死亡,從而判斷是否執(zhí)行 GC 操作。
優(yōu)點:
- 簡單
- 計算代價分散
- “幽靈時間”短(幽靈時間指對象死亡到回收的這段時間,處于幽靈狀態(tài))
缺點:
- 不全面(容易漏掉循環(huán)引用的對象)
- 并發(fā)支持較弱
- 占用額外內(nèi)存空間
例子如圖:
初始狀態(tài):

改變引用后:

標(biāo)記–清除算法(Mark-Sweep)
算法思想:
為每個對象存儲一個標(biāo)記位,記錄對象的狀態(tài)(活著或是死亡)。分為兩個階段,一個是標(biāo)記階段,這個階段內(nèi),為每個對象更新標(biāo)記位,檢查對象是否死亡;第二個階段是清除階段,該階段對死亡的對象進行清除,執(zhí)行 GC 操作。
優(yōu)點
- 最大的優(yōu)點是,相比于引用計數(shù)法,標(biāo)記—清除算法中每個活著的對象的引用只需要找到一個即可,找到一個就可以判斷它為活的。
- 此外,這個算法相比于引用計數(shù)法更全面,在指針操作上也沒有太多的花銷。更重要的是,這個算法并不移動對象的位置(后面?zhèn)z算法涉及到移動位置的問題)。
缺點
- 很長的幽靈時間,判斷對象已經(jīng)死亡,消耗了很多時間,這樣從對象死亡到對象被回收之間的時間過長。
- 每個活著的對象都要在標(biāo)記階段遍歷一遍;所有對象都要在清除階段掃描一遍,因此算法復(fù)雜度較高。
- 沒有移動對象,導(dǎo)致可能出現(xiàn)很多碎片空間無法利用的情況。
例子如圖
這個圖中,圓圈內(nèi)灰色的對象就是已經(jīng)死亡的對象,被標(biāo)記為死亡,等待清除。

標(biāo)記–整理算法
算法思想
標(biāo)記-整理法是標(biāo)記-清除法的一個改進版。同樣,在標(biāo)記階段,該算法也將所有對象標(biāo)記為存活和死亡兩種狀態(tài);不同的是,在第二個階段,該算法并沒有直接對死亡的對象進行清理,而是將所有存活的對象整理一下,放到另一處空間,然后把剩下的所有對象全部清除。這樣就達到了標(biāo)記-整理的目的。
優(yōu)點
- 該算法不會像標(biāo)記-清除算法那樣產(chǎn)生大量的碎片空間。
缺點
- 如果存活的對象過多,整理階段將會執(zhí)行較多復(fù)制操作,導(dǎo)致算法效率降低。
例子
如圖:

上面是標(biāo)記階段,下面是整理之后的狀態(tài)??梢钥吹?,該算法不會產(chǎn)生大量碎片內(nèi)存空間。
復(fù)制算法
算法思想
該算法將內(nèi)存平均分成兩部分,然后每次只使用其中的一部分,當(dāng)這部分內(nèi)存滿的時候,將內(nèi)存中所有存活的對象復(fù)制到另一個內(nèi)存中,然后將之前的內(nèi)存清空,只使用這部分內(nèi)存,循環(huán)下去。
注意:
這個算法與標(biāo)記-整理算法的區(qū)別在于,該算法不是在同一個區(qū)域復(fù)制,而是將所有存活的對象復(fù)制到另一個區(qū)域內(nèi)。
優(yōu)點
- 實現(xiàn)簡單
- 不產(chǎn)生內(nèi)存碎片
缺點
- 每次運行,總有一半內(nèi)存是空的,導(dǎo)致可使用的內(nèi)存空間只有原來的一半。
總結(jié)
不同算法有不同的優(yōu)點和缺點,除了引用計數(shù)法不常用外,其他三種算法在現(xiàn)在的java虛擬機上也是很常見的,間接說明了這幾個經(jīng)典算法還是有其適用性的。
理解 JVM 的 GC 算法能夠幫助我們更好地理解java的垃圾回收機制,例如,在 JVM 的年輕代使用的是復(fù)制算法來進行垃圾回收(由于其中的存活對象比例較?。?;而在老年代,使用的卻是標(biāo)記-清除法或標(biāo)記-整理法(由于每次回收都只回收少量對象)
到此這篇關(guān)于JVM中四種GC算法案例詳解的文章就介紹到這了,更多相關(guān)JVM中四種GC算法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringMVC中的@RequestMapping注解解析
這篇文章主要介紹了SpringMVC中的@RequestMapping注解解析,SpringMVC使用@RequestMapping注解為控制器指定可以處理哪些?URL?請求,在控制器的類定義及方法定義處都可標(biāo)注@RequestMapping,需要的朋友可以參考下2023-12-12
Spring Boot 通過 Mvc 擴展方便進行貨幣單位轉(zhuǎn)換的代碼詳解
這篇文章主要介紹了Spring Boot 通過 Mvc 擴展方便進行貨幣單位轉(zhuǎn)換,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
詳解Spring Cloud 斷路器集群監(jiān)控(Turbine)
這篇文章主要介紹了詳解Spring Cloud 斷路器集群監(jiān)控(Turbine),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
SpringBoot詳解如果通過@Value注解給靜態(tài)變量注入值
這篇文章主要介紹了springboot如何通過@Value給靜態(tài)變量注入值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06

