來自JVM的靈魂拷問:“你是什么垃圾?”
作者:iMononoke
博客:https://juejin.im/user/5c629a3051882562191755d8
GC是啥?
GC是一種自動(dòng)的存儲(chǔ)管理機(jī)制。當(dāng)一些被占用的內(nèi)存不再需要時(shí),就應(yīng)該予以釋放。這種存儲(chǔ)資源管理,稱為垃圾回收。
就和平時(shí)你清理桌面,整理東西一樣,很多人都見過聽過一個(gè)理念“斷舍離”吧,不會(huì)使用到的物品可以捐贈(zèng)給其他人或者作為可回收物品被回收掉,很多時(shí)候我們存著一些物品,但是好幾年都沒有用到它們,只是想著可能什么時(shí)候會(huì)用到,這樣一直占據(jù)著現(xiàn)實(shí)的“內(nèi)存”。
“臟亂差”
“干凈~”
還“活著”嗎?
在0-1的世界里,所謂“垃圾回收”,就是指收回那些不可能再被任何途徑使用的對(duì)象所占的內(nèi)存空間,釋放了這些內(nèi)存可以給需要的對(duì)象使用。
那么JVM里是怎么來分的?或者說哪些對(duì)象是需要被回收的?
主要是問一句:還“活著”嗎?
要回收,先要判斷是不是可以回收,就是這個(gè)對(duì)象還“活著”嗎?
主要有兩種算法來判斷:
- 引用計(jì)數(shù)法
- 可達(dá)性分析法。
列個(gè)表看看~
引用計(jì)數(shù)法
最大的問題,是很難解決對(duì)象之間互相引用的情況。
一圖勝千言。
1 互相引用
這是兩個(gè)對(duì)象互相引用的情況,除此之外,這兩個(gè)對(duì)象再無引用,但因?yàn)樗鼈兊囊糜?jì)數(shù)不為0,所以引用計(jì)數(shù)器無法通知GC收集器回收它們。
2 循環(huán)引用
這是循環(huán)引用的情況,沒有外部引用指向它們,但它們的引用計(jì)數(shù)不為0,就無法進(jìn)行回收了。
比如一把椅子的靠背壞了,椅子的輪子還是好的,但這輪子不能拆下來挪為他用,所以椅子的靠背和它的輪子是互相引用的,但是除了它們自己,沒有外界引用它們了。
這樣的情況用“引用計(jì)數(shù)法”來判斷的話,它們還是不用被回收的,但實(shí)際它們都沒有使用作用了。
所以主流的jvm都不使用引用計(jì)數(shù)法來管理內(nèi)存,而是采用下面的可達(dá)性分析法,下圖是它的基本思路示意圖。
- 可達(dá)性分析法
由圖可知,object5、object6和object7都沒有到GCRoots對(duì)象的引用鏈,它們都會(huì)被回收。
按照上面的例子,壞了的椅背和沒壞的輪子都屬于椅子對(duì)象(object5),但是椅子本身不被使用,就沒有引用到它們的引用鏈了。
可以做GC Roots的對(duì)象
這個(gè)大圖是不是挺熟悉?
再歸個(gè)類~
- 第一次:對(duì)象可達(dá)性分析之后,發(fā)現(xiàn)沒有與GCRoots相連接,此時(shí)會(huì)被第一次標(biāo)記并篩選。
- 第二次:對(duì)象沒有覆蓋finalize()方法,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過,此時(shí)會(huì)被認(rèn)定為沒必要執(zhí)行。