2011-12-12 4 views
17

czytałem to pytanie, które właśnie dostałem pytanie: Avoid memory leaks in callbacks?Czy anonimowi słuchacze są niekompatybilni ze słabymi referencjami?

i byłem zupełnie zdezorientowany, aż ktoś odpowiedział na następujące:

„Problem z tym podejściem jest to, nie może mieć słuchacza, który odwołuje się tylko w kolekcji jako zniknie losowo (na następnym GC)”

mam rację w moim rozumieniu, że za pomocą słabe odwołania, jak przy przechowywaniu w WeakHashMap, jest niezgodna z anonimowych słuchaczy?

I zwykle przechodzą słuchaczy tak:

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) 
    } 

} 

I śledzić słuchaczy za pomocą CopyOnWriteArrayList (domyślne Obserwowalne powyżej najwyraźniej wykorzystuje starą Vector ale jego tylko przykład do pokaż, jak zwykle tworzę anonimową klasę, która posłuży jako słuchacz).

Jako pytanie dodatkowe: kiedy odwołanie do anonimowego odbiorcy kwalifikowałoby się do GC, gdyby obserwowalny obiekt korzystał z WeakHashMap? Gdy metoda zakończy działanie? Jak tylko zakończone zostanie wywołanie obs.addObserver?

Jestem nieco zdezorientowany tym, gdzie/jak/kiedy odniesienia do anonimowych wystąpień klas są przechowywane/przechowywane/niewidoczne dla GC.

Oczywiście, jeśli zachowuję normalne odniesienie, to nie kwalifikuje się do GC, ale co, kiedy jest w WeakHashMap, kiedy dokładnie słuchacza stają się widoczne dla GC?

Odpowiedz

3

Jeśli obiekt jest tylko kluczem WeakHashMap, kwalifikuje się i prawdopodobnie zostanie wyczyszczony w następnym GC.

Cała idea używania zbioru ze słabym odwołaniem polega na niejawnym usunięciu detektorów, które nie są już przywoływane. (To pozwala uniknąć wycieku pamięci) Problem polega na tym, że słuchacz może zostać usunięty przedwcześnie i "losowo" w czasie.

+1

Dziękuję za pomoc, rozumiem to.Ale moje pytanie naprawdę odnosi się do anonimowych słuchaczy: jeśli umieściłem odniesienie do anonimowego słuchacza w WeakHashMap, czy istnieje inne odniesienie do tego anonimowego słuchacza trzymanego gdzieś indziej? Jeśli nie, to w którym momencie GC staje się niewidoczny? Po jakim telefonie? –

6

Tak, masz rację, słuchalna klasa utrzymująca słuchaczy ze słabymi referencjami (tak jak WeakHashMap) wymaga ich niezależnego wytrwałości. Może być używany dla hierarchii słuchaczy, w której słuchacz ma dzieci i rodzica.

Dla zastosowań innych niż WeakReference należy wywołać jawne removeListener. Chyba że obiekt słuchacza może żyć tak długo jak obiekt, który można słuchać. W większości przypadków jest to w porządku, a zrobi to anonimowa klasa.

Z przypadkach anonimowych Klasa A wyciek (zapobieganie GC) może nastąpić tylko przy dostępie do ostateczną obiektu poza ciałem klasy.

Uwaga: WeakHashMap i.a. używa słabych referencji dla własnej podklasy Map.Entry. Które mogą czasami być dość zadziwiające.

Powiązane problemy