¿Por qué se trata de una pérdida de memoria
Me encontré con una biblioteca para la detección de fugas de memoria en Android (Java) llamado LeakCanary, pero no puede entender el ejemplo donde se fugan de la memoria. ¿Podría alguien explicar cómo y por qué el código mostrado en su ejemplo es una pérdida de memoria.
class Cat { } class Box { Cat hiddenCat; } class Docker { static Box container; } // ... Box box = new Box(); Cat schrodingerCat = new Cat(); box.hiddenCat = schrodingerCat; Docker.container = box;
Y entonces miran la variable schrodingerCat
para los escapes que da una fuga demostrada como sigue (que no sé relacionarse al código antedicho).
- Error de apertura del archivo HPROF
- Java - android UDP falta de fiabilidad
- Problema con la descarga de varios archivos con AsyncTask
- Android Surfaceview Hilos y fugas de memoria
- Pocas pérdidas de memoria en Facebook SDK
* GC ROOT static Docker.container * references Box.hiddenCat * leaks Cat instance
Cualquier ayuda con la explicación de la fuga y cómo la detección se relaciona con ella sería muy provechosa. También algunos buenos artículos para los principiantes sería agradable.
¡Gracias!
- Actividad ha filtrado ventana com.android.internal.policy.impl.PhoneWindow$DecorView@44f72ff0 que fue agregado originalmente aquí
- Investigación de LeakCanary: com.motorola.pixelpipe.PixelPipeTarget.mContext
- Memoria interna llena de imágenes, probablemente causada por Bitmap.compress (formato, int, flujo)
- LeakCanary detecta pérdida de memoria de Android WebView
- Atascado en "Vaciar memoria, la aplicación se congelará. Brrr. "Mensaje
- Leyendo LeakCanary Log
- Cómo utilizar Leak Canary
- Gestión de memoria HttpClient
En primer lugar, vamos a entender lo que es un escape de memoria :
Definición
Memory Leak se asigna a los datos (bitmaps, objetos, matrices, etc) en la RAM que el recolector de basura (GC) no puede liberar, aunque ya no es necesario por el programa.
Ejemplo
Un usuario está abriendo una vista que muestra una imagen. Cargamos el mapa de bits a la memoria. Ahora el usuario sale de la vista y la imagen ya no es necesaria y no hay referencia a ella desde el código. En ese momento el GC entra en acción y lo retira de la memoria. PERO , si todavía teníamos una referencia a él, el GC no sabrá que está bien para la eliminación y se habría quedado en la memoria RAM tomando espacio innecesario – aka Memory Leak .
Gato en una caja
Digamos que tenemos un objeto Cat en nuestra aplicación, y lo mantenemos en un objeto Box. Si mantenemos la casilla (tenemos una referencia al objeto Box) y el Box contiene el Cat, el GC no podrá limpiar el objeto Cat de la memoria.
El Docker es una clase que tiene una referencia estática a nuestra caja. Esto significa que a menos que lo anule o reasigne el valor, el Docker seguirá haciendo referencia a la Caja. Prevención de la Caja (y el gato interior) de ser retirado de la memoria por el GC.
Entonces, ¿necesitamos el gato? ¿Sigue siendo relevante para la aplicación?
Esto es hasta el desarrollador para decidir cuánto tiempo necesitamos el gato para. LeakCanary y otras herramientas de diagnóstico sugieren un posible escape de memoria. Ellos piensan que el objeto (Cat) podría no ser necesario más así que alertan que es una fuga.
Resumen
En el ejemplo, dan un escenario común de una pérdida de memoria. Cuando se utiliza una referencia estática, evitamos que el GC limpie un objeto. Usted debe leer esto:
* GC ROOT static Docker.container * references Box.hiddenCat * leaks Cat instance
como:
- Objeto Gato podría no ser utilizado más, pero no fue retirado de la memoria por el GC.
- La razón por la que el objeto Cat no se eliminó es porque Box tiene una referencia a él.
- La razón por la que el objeto Box no se ha eliminado es porque el Docker tiene una referencia estática.
- La referencia estática por Docker es la ROOT del árbol que causa la posible fuga.
Parece que la instancia de RefWatcher
utiliza para "ver la variable schrodingerCat
para las filtraciones":
refWatcher.watch(schrodingerCat);
Fuerza un conjunto de GC pasa y si la referencia pasada no se recoge durante esos GC pasa se considera una fuga.
Puesto que el Docker.container.hiddenCat
estático está manteniendo una referencia enraizada GC al objeto originalmente conocido como schrodingerCat
, no puede ser GC'ed así que cuando pides RefWatcher
para comprobarlo. Por lo tanto, le permite saber que el objeto no se puede recopilar.
Le sugiero que lea esta respuesta https://stackoverflow.com/a/11908685/1065810
Probablemente le ayudará a entender el ejemplo anterior.
En resumen, en su ejemplo, la clase Docker mantiene una referencia a una caja. Incluso cuando ya no se necesita la caja contenedora, la clase Docker todavía tiene una referencia a ella creando así una pérdida de memoria.
Déjeme saber si eso ayuda.
- Android ImageButton – determina qué recurso está configurado actualmente
- Android N Preview emulator crash