uso una superclase que polimorfismo metodos metodo llamar herencia como clase java android memory-leaks anonymous-class

java - superclase - ¿La referencia al objeto final en el constructor de clase anónimo es una fuga?



superclase java (3)

Estoy pasando un ejecutable a un servicio. La duración ejecutable puede sobrevivir al fragmento / actividad que lo pasa. Me pregunto si el siguiente fragmento de código podría filtrar el objeto frag manteniendo una referencia dentro del ejecutable. Me doy cuenta de que puedo mover toda la línea que contiene frag fuera del ejecutable (como lo hice con "String key = frag ..."), pero estoy pidiendo simplemente para obtener una comprensión de cómo / cuándo una clase anónima se filtraría una objeto.

Realmente no estoy seguro. El ejecutable solo necesita frag para determinar una variable al inicializar la instancia, y se inicializa en línea aquí. Entonces, en teoría, no necesita tener ninguna referencia a frag después de crear la instancia en línea.

Si tuviera una referencia a frag en la función run (), pensaría que una fuga estaría garantizada, ya que necesitaría mantener frag fragmentada para referenciarla en el futuro (y frag podría estar muy bien en ese momento) punto, pero para la referencia).

private static void fg_downloadFile(final FragMyDrive frag, final File file, final Drive drive){ final String key = frag.getCastedActivity().getKey(); Runnable rx_downloadFile = new Runnable() { Context ServiceContext = frag.getCastedActivity().mService; @Override public void run() { bg_downloadFile(ServiceContext, key, file, drive); } }; //.... Submit runnable to service... }


Como ya sabrá, debe hacer que las variables sean definitivas cuando las declare fuera pero las use en una clase anónima. El truco de Java aquí es copiar todas esas variables en campos de instancia generados implícitamente de esa clase anónima.

Una vez dicho esto, significa que efectivamente hay campos de instancia (en su ejecutable) que contienen copias de todas las variables accedidas del alcance externo. En su ejemplo, también tendría una referencia al FragMyDrive ya que simplemente está accediendo a él.

Todos esos objetos se vuelven elegibles para la recolección de basura al mismo tiempo que su ejecutable se vuelve elegible para la recolección de basura. Eso significa que la referencia a su FragMyDrive dentro de su ejecutable mantiene vivo ese objeto mientras esté en ejecución.

Siempre es una buena idea reducir esas referencias a lo que realmente necesita:

private static void fg_downloadFile(final FragMyDrive frag, final File file, final Drive drive){ final String key = frag.getCastedActivity().getKey(); final Context context = frag.getCastedActivity().mService; Runnable rx_downloadFile = new Runnable() { @Override public void run() { bg_downloadFile(context, key, file, drive); } }; //.... Submit runnable to service... }

Aquí los únicos campos de instancia (generados implícitamente) son:

String key Context context File file Drive drive


Interesante pregunta. ¿Tiene alguna experiencia en programación sin recolección automática de basura, como Objective C?

Pero para responder a su pregunta, no veo por qué sería una filtración. Lo que supongo que sucederá es que Runnable guardará una referencia a frag para su propio uso, pero en algún punto en el futuro, frag también obtendrá basura recolectada una vez que el servicio ya no la necesite y, por lo tanto, no se refiere a eso.

Como la recolección de basura funciona, una vez que un objeto ya no se referencia, estará sujeto a la recolección de basura y desasignado.


No estoy seguro de entender su uso de la palabra en línea correctamente, pero en cualquier caso, no creo que se filtre nada aquí.

Var final String key es simplemente una referencia local en su función estática fg_downloadFile() por lo que se libera al salir del ámbito al final de la función.

La clase interna anónima Runnable aún puede contener una referencia (una vez más, no para frag sino para alguna propiedad secundaria) mientras dure el hilo Runnable . (Más precisamente, el compilador en realidad genera una implementation de Runnable con un constructor y variables miembro final que copian las referencias implícitamente usadas a lo que esté disponible en el alcance de fg_downloadFile() ).

Pero en cualquier caso, una vez que se haya ejecutado todo el código, todas las referencias a (sub-miembros de) frag se eliminarán y el recolector de basura puede recoger la basura.

Espero que esto ayude.