Java中單例對象不會被GC回收

  hotspot虛擬機的垃圾收集算法使用根搜索算法。這個算法的基本思路是:對任何「活」的對象,必定能最終追溯到其存活在堆棧或靜態存儲區之中的引用。經過一系列名爲根(GC Roots)的引用做爲起點,從這些根開始搜索,通過一系列的路徑,若是能夠到達java堆中的對象,那麼這個對象就是「活」的,是不可回收的。能夠做爲根的對象有:java

  • 虛擬機棧(棧楨中的本地變量表)中的引用的對象。
  • 方法區中的類靜態屬性引用的對象。
  • 方法區中的常量引用的對象。
  • 本地方法棧中JNI的引用的對象。

     方法區是jvm的一塊內存區域,用來存放類相關的信息。很明顯,java中單例模式建立的對象被本身類中的靜態屬性所引用,符合第二條,所以,單例對象不會被jvm垃圾收集。算法

            雖然jvm堆中的單例對象不會被垃圾收集,可是單例類自己若是長時間不用會不會被收集呢?由於jvm對方法區也是有垃圾收集機制的。若是單例類被收集,那麼堆中的對象就會失去到根的路徑,必然會被垃圾收集掉。對此,筆者查閱了hotspot虛擬機對方法區的垃圾收集方法,jvm卸載類的斷定條件以下:jvm

    • 該類全部的實例都已經被回收,也就是java堆中不存在該類的任何實例。
    • 加載該類的ClassLoader已經被回收。
    • 該類對應的java.lang.Class對象沒有任何地方被引用,沒法在任何地方經過反射訪問該類的方法。

            只有三個條件都知足,jvm纔會在垃圾收集的時候卸載類。顯然,單例的類不知足條件一,所以單例類也不會被卸載。也就是說,只要單例類中的靜態引用指向jvm堆中的單例對象,那麼單例類和單例對象都不會被垃圾收集,依據根搜索算法,對象是否會被垃圾收集與未被使用時間長短無關,僅僅在於這個對象是否是「活」的。對象

相關文章
相關標籤/搜索