2011-12-12 15 views
17

estaba leyendo esta pregunta que acaba de ser preguntó: Avoid memory leaks in callbacks?¿Los oyentes anónimos son incompatibles con las referencias débiles?

Y yo estaba bastante confundido, hasta que alguien respondió lo siguiente:

"El problema con este enfoque es que no se puede tener un oyente que sólo se hace referencia en la colección, ya que desaparecerá al azar (en la siguiente GC)"

Estoy en lo correcto en mi entendimiento de que el uso de unas referencias débiles, como cuando se almacena en un WeakHashMap, es incompatible con los oyentes anónimos?

Me suelen pasar los oyentes de esta manera:

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

} 

Y no perder de vista los oyentes usando un CopyOnWriteArrayList (el valor por defecto observable por encima de parecer utiliza un viejo vector pero es sólo un ejemplo de mostrar cómo normalmente creo una clase anónima para usar como oyente).

Como una pregunta de bonificación: ¿cuándo sería la referencia al oyente anónimo elegible para GC si el sujeto observable utilizara un WeakHashMap? Cuando sale el método principal? ¿Tan pronto como finaliza la llamada obs.addObserver?

Estoy un poco confundido acerca de dónde/cómo/cuándo las referencias a instancias de clases anónimas se guardan/almacenan/elligible para GC.

Obviamente, si mantengo una referencia normal, no es elegible para GC, pero ¿qué ocurre cuando está en un WeakHashMap, cuando es exactamente el oyente se vuelve elegible para GC?

Respuesta

3

Si un objeto es solo una clave de un WeakHashMap, entonces es elegible y es probable que se limpie en el siguiente GC.

La idea de utilizar una colección de referencia Débil es eliminar implícitamente oyentes a los que ya no se haga referencia. (Esto evita la posibilidad de una pérdida de memoria) El problema es que el oyente puede eliminarse prematuramente y en un momento "aleatorio".

+1

Gracias por su ayuda, lo entiendo.Pero mi pregunta realmente se relaciona específicamente con los oyentes anónimos: si pongo una referencia a un oyente anónimo en un WeakHashMap, ¿hay alguna otra referencia a ese oyente anónimo guardado en otro lugar? Si no, ¿en qué momento se vuelve elegible para GC? ¿Después de qué llamada? –

6

Sí, tienes razón, una clase escuchable que mantiene a los oyentes con referencias débiles (como lo hace WeakHashMap) requiere su persistencia independiente. Podría usarse para jerarquías de escucha donde un oyente tiene hijos y un padre.

Para usos que no sean WeakReference, debe llamarse a un removeListener explícito. A menos que el objeto oyente pueda vivir tanto como el objeto escuchable. En la mayoría de los casos de uso, eso está bien, y una clase anónima lo hará.

Con instancias de la clase anónimos un fuga (prevención GC) solamente puede suceder cuando se accede a una final objeto fuera del cuerpo de la clase.

Nota: WeakHashMap i.a. utiliza referencias débiles para su propia subclase de Map.Entry. Que a veces puede ser bastante alucinante.

Cuestiones relacionadas