2011-12-12 37 views
17

我讀這問那剛剛問:Avoid memory leaks in callbacks?匿名監聽器是否與弱引用不兼容?

而且我十分困惑,直到有人回答如下:

「這種方法的問題是你不能擁有它僅引用一個監聽器因爲它會隨機消失(上接GC)集」

我是在我的理解是否正確在使用弱引用,當存儲在一個WeakHashMap中一樣,是匿名的聽衆不兼容?

我通常通過監聽器是這樣的:

public static void main(String[] args) { 
    final Observable obs = new SomeObservable(); 
    obs.addObserver(new Observer() { 
     public void update(final Observable o, final Object arg) { 
      System.out.println("Notified"); 
     } 
    }); 
    obs.notifyObservers(); 
    ... // program continues its life here 
} 

private static final class SomeObservable extends Observable { 

    @Override 
    public void addObserver(final Observer o) { 
     super.addObserver(o); 
     setChanged(); // shouldn't be done from here (unrelated to the question) 
    } 

} 

我使用的CopyOnWriteArrayList(默認可觀察上面顯然使用舊矢量但它只是一個例子來跟蹤監聽器顯示我通常如何創建一個匿名類用作偵聽器)。

作爲一個額外的問題:如果可觀察主體使用WeakHashMap,那麼對匿名監聽器的引用何時符合GC的條件?當主要方法退出?一旦obs.addObserver呼叫結束了?

我對有關匿名類實例的引用在何處/如何/何時被保存/存儲/保存爲GC有些困惑。

顯然,如果我保持一個正常參考它沒有資格GC,但什麼時候是WeakHashMap中,什麼時候正是聽者的GC成爲elligible?

回答

3

如果一個對象只是WeakHashMap的關鍵字,那麼它就符合條件並可能在下一個GC中清除。

使用弱引用集合的整個想法是隱式刪除不再引用的偵聽器。 (這避免了內存泄漏的可能性)問題是可以在「隨機」時間點過早地移除偵聽器。

+1

感謝您的幫助,我明白這一點。但是我的問題確實涉及到匿名監聽器:如果我在WeakHashMap中引用匿名監聽器,那麼是否還有另一個對該匿名監聽器的引用保存在別的地方?如果沒有,那麼在哪個時候確實可以用於GC?在哪個電話之後? –

6

是的,你是對的,一個可監聽的類保持弱引用的監聽器(就像WeakHashMap一樣)需要它們的獨立持久性。可以用於監聽器有子代和父代的監聽器層次結構。

對於non-WeakReference用法,必須調用顯式removeListener。除非聽者對象可以像可聽對象一樣長。在大多數情況下,這是很好的,而且一個匿名類將會這樣做。

使用匿名類實例一泄漏(GC預防)訪問類身體外部的最終對象時,可能僅發生。

注意:WeakHashMap i.a.對它自己的Map.Entry的子類使用弱引用。有時這可能令人難以置信。