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