2013-03-19 65 views
3

我知道System.gc()不能保證導致GC,但理論上,在下面的代碼中,對象obj是否有資格進行垃圾回收?對象是否符合「obj = null」之後垃圾回收的條件?

public class Demo { 

    public static void main(String[] args) throws Exception { 
     SomeClass obj = new SomeClass(); 
     ArrayList list = new ArrayList(); 
     list.add(obj); 
     obj = null; 
     System.gc(); 
    } 

} 

class SomeClass { 
    protected void finalize() { 
     System.out.println("Called"); 
    } 
} 
+3

也不能保證'finalize'永遠不會被調用 – MadProgrammer 2013-03-19 06:15:09

+0

不符合條件,因爲您的obj引用爲空,但在存在的列表中仍然可以訪問。 – 2013-03-19 06:17:08

+1

雖然答案是「否」(假設變量始終是強根),但這是一個有趣的觀點。在.NET/C#中,SomeClass對象*可能*被垃圾回收,因爲'list'本身並未被使用[稍後]。這是一個長時間運行的方法中帶有定時器回調的實際.NET問題。問題是:*在Java *中,*可見堆棧中的每個*變量*總是*保證是一個強壯的根? – 2013-03-19 06:52:56

回答

9

,在您打電話System.gc()您所創建的SomeClass實例符合垃圾收集,因爲它是由list對象仍稱,該點即它仍然是可達

但是,只要此方法返回list超出範圍,那麼obj就會變爲符合垃圾回收的條件(與list一樣)。

只需將參考obj設置爲null,本身不會使對象引用符合垃圾回收條件。如果有一個對象從可見對象的圖形中引用了沒有,那麼它只適用於該對象。

+0

當您將obj設置爲null時,它是否不會在列表中變爲null? List只是指向obj早些時候的同一個位置。 – 2013-03-19 06:19:58

+5

No. Java使用引用,而不是指針。當您將一個項目添加到列表中時,它將獲取該參考的一個副本並將其存儲。更改原始引用不會更改複製的引用,所以'SomeClass'實例仍然可以訪問。 – 2013-03-19 06:20:53

+0

同意,在上述情況下不會收集垃圾。 – 2013-03-19 06:25:34

-2

同意,只要它在列表中,它就不會被垃圾收集。

+1

答案是否定的。儘快閱讀「Head First Core Java」。 – AmitG 2013-03-19 06:21:00

3

不,因爲該對象實際上存在於列表中。

1

作爲Java程序員的你不能在Java中強制垃圾收集;它只會在JVM認爲需要基於Java堆大小的垃圾回收時觸發。

啓動Java程序時Java虛擬機從操作系統獲取一些內存。 Java虛擬機或JVM使用這個內存來滿足它的所有需求,這部分內存就是調用java堆內存。

Java中的堆一般位於地址空間的底部並向上移動。每當我們使用新的運營商或通過任何其他方式對象創建對象從堆分配的內存和當對象死亡或垃圾收集,存儲追溯到堆空間的Java

編輯:

會把對象obj有資格進行垃圾回收?

不,因爲該對象仍在ArrayList中。

+1

問題是關於對象是否符合垃圾回收*。 – 2013-03-19 06:19:22

+0

@CameronSkinner他在代碼中調用System.gc()。 – 2013-03-19 06:20:13

+1

是的,他是。他還指出,他知道它不會強制垃圾收集運行。你還沒有回答這個問題:「對象'obj'是否有資格進行垃圾回收?」 – 2013-03-19 06:22:37

4

對象obj是否有資格進行垃圾回收?

只有這些對象是垃圾收集的人誰甚至沒有一個引用到達他們。 (除循環連接)

在你的代碼,但是也有一些指向new SomeClass();

  1. OBJ
  2. 列表

你把obj = null

  • 零指數兩個基準,即它不是指向那個對象了。但是,在列表中還存在另一個可用於訪問該對象的參考。

    因此,只有當main返回時,該對象纔有資格使用GC。即使它被調用,也看不到finalize方法的輸出。 (不確定JVM是否仍然調用它)

  • +0

    「list」是一個強根的保證在哪裏? (我確定它是在一些規範中:-)在調用'System.gc'之後,'list'對象不會被使用*,因此在技術上它並不是「需要」,因此可能(這是我不確定這些保證)可能是垃圾收集本身的限定條件?或者,callframe的存在*要求*在所有條件下所有局部變量都是強根?即使在JIT之後? – 2013-03-19 07:02:17