在上一篇文章中,我介紹了關於GC機制中,GC在確認垃圾對象後,是如何回收這些垃圾對象的幾種算法。如今介紹下GC機制通常是如何定位(或者叫作標記)出這些垃圾對象的。
咱們先來問下本身,如何判介紹了斷一個對象能夠被回收。
答案很簡單也很直白。這個對象不再會被調用到了 ,那麼就能夠被回收了。
那麼怎麼判斷一個對象不再會被別人調用呢?
答案也很簡單,只要其餘的對象不再持有當前對象的引用了,那麼就能夠被收回了。
結合以上的思路,基本就能夠肯定什麼樣的對象能夠被標記爲垃圾對象了。
基於此,一般被提到的用於定位垃圾對象的兩種算法以下:
一、可達性分析法 Reachabbility Analysis
二、引用計數算法 Reference Counting
本文主要介紹第一種算法,第二種算法會在下篇文章中介紹。html
可達性分析算法
可達性分析法大體思路是先肯定出哪些對象必定不會被回收,而後將這些對象做爲根,一次遍歷這些根持有的引用,直至最終完整個森林。而這些遍歷到的對象,就認爲是能夠到達,能夠引用到的對象,將這些對象標記後,剩餘未被標記的對象就能夠認爲是不可訪問的垃圾對象了。
以下圖所示算法
優勢
這種方法不管是算法思路,仍是算法的實現,都是很是簡單 的。同時執行的偏差很是小,能夠處理包括循環引用(如上圖中黃色的內存部分)在內的不少異常場景。所以自問世以來,大部分
的GC中,均可以看到該算法的影子。
缺點
一、簡單是簡單,惋惜速度不夠快。每次計算時都須要從根開始遍歷。
二、對於只有極少數變量須要回收的場景,這種算法的性價比過低了。
三、對主程序的影響比較大,因爲須要從根開始逐層探索,所以(防盜鏈接:本文首發自http://www.cnblogs.com/jilodream/ )在遍歷的過程當中,對象間的關係不能再發生變化,所以須要主程序暫停運行(這個時間段也常被稱爲Stop The World)。每每對於一些須要及時響應的場景,這種狀況是很是不友好的。
那麼究竟有哪些對象能夠做爲這個算法根存在呢?換句話說就是有哪些對象確定不會被刪除呢?
在JVM當中,有如下幾種狀況:
一、虛擬機棧中,棧幀中局部變量表所存放的變量引用
這些引用表明當前正在執行的方法中,所持有的引用。因爲篇幅有限,若是你對爲何棧幀中的局部變量表的對象能夠做爲根存在疑問,能夠看個人另一篇關於虛擬機內存的文章:https://www.cnblogs.com/jilodream/p/6147791.html
二、方法區中靜態屬性引用的對象
這些引用表示的是類對象中,靜態變量持有的引用。類一旦被加載,其中的靜態變量不會隨某一個實例對象的回收而回收。
三、方法區中常量的引用信息:方法區中常量引用的信息。
四、本地方法棧中,native方法正在使用的變量:虛擬機本地方法使用的變量。
以上對象並非絕對的永遠的能夠做爲算法的根存在。當類被卸載、常量被回收時,一些原本會被做爲根的對象也會被回收。所以在回收時,具體以哪些對象做爲可達性分析的根對象,虛擬機會根據狀況再作決定。
因爲篇幅有限,這裏只介紹可達性分析法,至於引用計數算法我會放在下一篇文章中總結介紹。spa