1. 程式人生 > >物件已死麼

物件已死麼

    垃圾回收前需要知道哪些物件需要被收集,就需要知道哪些物件是死了還是活的。下面就是知道哪些物件是死是活的演算法。

引用計演算法

    引用計數演算法是每次使用一個物件的時候就加1,不使用後就減1,為0了,就說明這個物件死了。但是java中沒有使用引用計數演算法,因為java中存在著迴圈引用的問題,所以不行。

可達性分析演算法

    通過一系列稱為GC roots的物件作為起始點,開始搜尋下面節點,當一個物件不能抵達GC roots時,這個物件就不可用,被判定為可回收物件。在java語言中,可作為GC roots的有1:虛擬機器棧中引用的物件;2.方法區中類靜態屬性引用物件;3.方法區中常量引用的物件;4.本地方法棧中jni引用的物件。

再談引用

引用分為四種:強引用;軟引用;弱引用;虛引用;

強引用:強引用類似於Object obj =new Object();只要強引用存在,就不會被回收。

軟引用:是用來描述一些還有用,但是非必須的物件。在系統將要發生記憶體溢位異常之前,將會把這些物件列進回收範圍進行二次回收,如果還是沒有足夠的空間,那麼將會丟擲異常。softreference類來實現軟引用。

弱引用:弱引用物件是也是用來描述非必須物件的,但是比軟引用還要弱,在垃圾收集器下一次進行回收的時候,無論記憶體是否足夠,都會被收集。weakreference來實現弱引用。

虛引用:虛擬引用也稱為幽靈引用,幻影引用。最弱的一種引用。一個物件是否有虛擬引用的存在,完全不會對其存在的時間產生影響,也無法通過一個虛擬引用得到一個物件例項。為一個物件設定一個虛擬引用關聯的唯一目的就是這個物件被回收的時候,收到一個系統通知。

生存還是死亡

一個物件即使在可達性分析演算法中被標記為不可達物件,這個時候只是被判定為緩刑,要等到第二次被判定,才有可能被回收。第一次標記的同時,還會進行一次篩選,篩選的條件就是此物件,是否有必要執行finalize()方法。當物件沒有覆蓋finalize()或者finalize()已被虛擬機器呼叫,,就會被虛擬機器視為沒有必要執行。

    如果確定需要執行finalize(),那麼這個物件會被放進一個F-queue的佇列,,由虛擬機器建立一個低優先順序的執行緒進行執行。這裡的執行只是觸發,並不會等他執行結束,這樣做的原因是當這個物件執行很慢,或者發生了死迴圈,那麼可能會導致記憶體回收系統的奔潰,finalize()方法是物件逃脫死亡的最後一次機會,只要他與引用鏈上的任何一個物件連結上就行了。GC進行第二次,小規模的標記,即將回收,那麼基本就會被回收,逃脫不了。一個物件的finalize()被執行,但是他仍然可以存活。這個方法是對c/c++程式的一種妥協,用try/catch等能做的更好,完全忘掉這個方法。

回收方法區

    回收方法區一般沒有垃圾收集器,這個地方垃圾收集的價效比太低,所以一般不處理這裡。但是這裡還是有垃圾收集器,有些引數可以設定,進行回收。

    在大量使用反射,動態代理,CGLib等bytecode框架。動態生成jsp以及OSGi這類頻繁自定義類載入的場景都需要虛擬機器具備類解除安裝的功能,以保證永久帶不會溢位。