2013-05-16 31 views
12

我已經通過在線閱讀了一些Java垃圾收集指南,但我仍然有點不清楚,希望確保在代碼中沒有內存泄漏。如果實例變量仍然有引用,Java GC是否銷燬對象?

Java GC是否收集丟失其引用的對象,但其變量仍有參考?

所以我們可以說我有SomeObject:

public class SomeObject { 
    public ObjectVar var; 

    public SomeObject() { 
     var = new ObjectVar(); 
    } 
} 

而且我的代碼:

SomeObject obj1 = new SomeObject(); 
SomeObject obj2 = new SomeObject(); 
obj2.var = obj1.var; 
obj1 = null; 

所以OBJ1的變種具有一定的參考,但OBJ1不再有任何引用。那麼,GC是否會銷燬obj1,但保持var還活着? (我假設如此,只是想確定)。謝謝!

+0

GC的基本規則是,如果GC對一個對象會影響你的程序,它不會發生。 (除非你使用關注GC的專門工具,但如果你使用的話,你會知道的。) –

+0

你可能想閱讀[「中年危機」](http://blogs.msdn。 COM/b /瑞康/存檔/ 2003/12/04/41281.aspx)。 – Mehrdad

回答

12

這裏是什麼事情發生(見下面的評論)

// obj1 and obj1.var get created 
SomeObject obj1 = new SomeObject(); 
// obj2 and obj2.var get created 
SomeObject obj2 = new SomeObject(); 
// old obj2.var becomes eligible for GC 
obj2.var = obj1.var; 
// obj1 becomes eligible for GC 
obj1 = null; 

最終,兩個對象仍然沒有得到GCD - obj2和前obj1.var這是目前被引用爲obj2.var

注:在ObjectVar類是一個非靜態內部類的SomeObject,保持一個參考obj1.var也將保持obj1圍繞一個特例。這是因爲SomeObject.ObjectVar類內部有一個類型爲SomeObject的隱藏變量,它引用內部類的外部對象。

+0

好的謝謝!但現在我很困惑,因爲兩個人有不同的答案。如果ObjectVar是SomeObject的子類(或內部類),上面的代碼將使obj1不符合GC的條件? – baekacaek

+1

@baekacaek ZyyaoWei的評論只考慮了靜態的內部類,在這種情況下它並不重要。非靜態內部類和匿名或命名方法局部類可以防止垃圾收集主機對象,但靜態內部類不能。 – dasblinkenlight

+0

再次感謝您的澄清和快速回復! – baekacaek

3

當然可以。

請記住,您在var字段中存儲的內容實際上是對象的引用,而不是對象本身。因此,當GC收集obj1,在var對象是不變(不得觸碰),特別是因爲它具有從obj2一個參考,這是仍然健在的..

+0

謝謝,如果ObjectVar是SomeObject的內部類,是否也適用? – baekacaek

+0

那應該不重要,因爲不管obj2是什麼引用該對象。 –

+2

如果它是一個靜態的內部類,那確實無關緊要。但是,當它是一個非靜態的內部類時,'var'對外部類有一個「反向引用」,這可能會讓所有者的活動時間超過預期的時間。 – dasblinkenlight

0

是的 - 行爲與您描述的一樣。垃圾收集的一般規則是,只有當通過任何硬引用無法訪問它們時,對象纔會變爲合格。任何可以達到這種方式的物體都將永遠不會被垃圾收集(除軟/弱參考外)。

0

簡而言之,如果某個對象仍然可以通過引用路徑到達,則它將保證能夠繼續收集。如果沒有這樣的路徑,則不能再訪問該對象,並且可以安全地收集該對象。

前兩行後,內存看起來是這樣的:

o1 --> SomeObj#1 --> ObjectVar#1 
o2 --> SomeObj#2 --> ObjectVar#2 

所有4個對象,可以達到,如果垃圾收集是在這個時候發生,沒有人會被收集。

3號線後,它看起來像這樣:

o1 --> SomeObj#1 --> ObjectVar#1 
        ^
o2 --> SomeObj#2 ----- ObjectVar#2 

現在,只有3個對象即可到達;垃圾收集器可能會刪除ObjectVar#2。

4號線後,它看起來像這樣:

o1  SomeObj#1 --> ObjectVar#1 
        ^
o2 --> SomeObj#2 ----- ObjectVar#2 

只有兩個對象依舊可達;垃圾收集器可能會刪除SomeObj#1和ObjectVar#2,但必須保留SomeObj#2和ObjectVar#1。