Gestión de Memoria en Android, Entendiendo Memory leaks

En la mayoría de aplicaciones Android no es necesario tener excesivo cuidado con la gestión de memoria, el GC(Garbage Collector) se encarga por nosotros de ir eliminando todos los elementos que han muerto en la aplicación. Esto no ocurre en otros lenguajes por ejemplo cuando se desarrolla una aplicación en iOS, donde eres el desarrollador el encargado de gestionar la memoria de cada elmento, reservando su espacio y liberandolo cuando ya no sea necesario.

¿Que es el GC(Garbage Collector)?

Es un sistema que automatiza la gestión de la memoria. Reservando cuando es necesaria, eliminando cuando ya no se usa, compactando cuando es mejor agruparla. La maquina dalvik de Android implementa un GC mas sencillo que el de java pero que es muy util.

Entonces ¿Que problema existe?

La manera en que trabaja Android, tiene parte buena y parte mala. La automatización de la gestión de memoria, hace que cuando te encuentras con un problema de desbordamiento o fuga de la pila de memoria, su solucion no es facil. Cuando estas desarrollando un juego o una aplicacion que requiere cargar en memoria muchas imagenes o un procesado de computacion alto, tienes que tener muchisimo cuidado, al menor despiste te encuentras con problemas. Yo ahora mismo estoy intentado resolver, en uno de mis juegos, un fallo “java.lang.OutOfMemoryError: bitmap size exceeds VM budget”.

Si me encuentro con un OutOfMemoryError, ¿Que puedo hacer?

1) Aprende a leer los mensajes del GC: Es muy importante conocer como esta funcionando el GC y que representa cada mensaje. Hay 5 tipos de mensajes:
– GC_CONCURRENT: Se activa cuando es necesario liberar memoria. De esta manera, se libera memoria antes de que haya una necesidad real, evitando hacer una pausa y llamar a la GC.
– GC_FOR_MALLOC: Significa que el GC fue disparado porque no habia suficiente memoria en la pila para realizar una asignacion. Puede ser activado cuando nuevos objetos estando siendo creados. Se activa cuando la pila está llena y tenemos que parar y esperar a que el GC para liberar memoria.
– GC_EXTERNAL_ALLOC: Significa que la VM esta intentando reducir el monton de memoria utilizado por coleciones de objetos, para hacer espacio para objetos que no son de colección como Bitpmap o buffers NIO.
– GC_HPROF_DUMP_HEAP: Si recoges la pila para examinarla
– GC_EXPLICIT: Cuando realizas una llamada explicita a “System.gc()”

Ahora que sabemos los tipos de mensajes, vamos a interpretar uno de ellos. Supongamos que en el LogCat hemos Obtenido:
D/dalvikm (9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703/5261, paused 2ms+2ms

Explicación: Acaba de liberarse 2049K, esta libre el 65% de memoria. Lo siguiente refiere a la memoria externa, el primer numero(3571) es el total de memoria externa que la aplicacion tiene alojada(imagenes y buffers NIO), el segundo número es una especie de límite flexible, que va aumentando segun las necesidades, hasta un punto limite segun la memoria de cada dispositivo. Finalmente el tiempo que ha consumido el GC en sus tareas.

2) Aprende a descargar el fichero hprof desde las herramientas DDMS, conviertelo a un formato valido y aprende a utilizar Eclipse Memory Analyzer

Yo estoy en proceso de aprendizaje con esta poderosa herramienta, asi que de ella tampoco podre aprotar demasiado, pero si como llegar hasta ella.
En primer lugar lanzamos la aplicacion Android en modo “debug” y nos vamos a la vista DDMS. Probamos la aplicación por sus diferentes partes, hasta que obtenemos un fallo o no necesariamente. Ahí seleccionamos en la pestaña “Devices” el proceso sobre el que corre nuestra aplicación y pulsamos el botón que podéis ver en la siguiente captura.

imagen del boton que hay que pulsar, se llama DUMP HPROF fileGuardamos el fichero que nos genera, con el nombre “dump.hprof” .Tras ello, tenemos que convertir el fichero que hemos guardado en otro formato, vamos con un terminal a donde tenemos el sdk de android y luego a la carpeta tools y hacemos lo siguiente:

$ hprof-conv dump.hprof dump-conv.hprof

Ya podemos abrir ese fichero generado (dump-conv.hprof) con MAT(Eclipse MemoryAnalyzer)

Si quieres aprender a dar tus primeos pasos en Eclipse MemoryAnalyzer y conocer mas cosas sobre la gestion de memoria en Android, te recomiendo que veas esta ponencia de unos de los ingenieros de google celebrada a mediados de 2011.

Espero postearos pronto nuevos trucos sobre la gestión de memoria en Android!

This entry was posted in Android. Bookmark the permalink.

5 Responses to Gestión de Memoria en Android, Entendiendo Memory leaks

  1. Juan Martin says:

    Muy buena la explicación. Es justo lo que estoy necesitando, mi app esta tirando el mismo outOfMemory error. Muchas gracias por compartir!

  2. eetayo says:

    Encantado de que te haya sido util! Por cierto tienes en este post, como solucione mi fuga de memoria http://www.estebanetayo.es/?p=459

  3. Juan Martin says:

    Muchas gracias!
    Hace unos minutos termine de mirar el video. La verdad ahora entiendo un poco mas todo. Estoy probando el MAT (Memory Analizer) y es muy util en estos casos, por ejemplo detecte una activity que tiene muchas instancias.

    El otro post lo vi primero, pero vine a leer este para entender lo básico, enseguida sigo leyendo el otro.

    Muchas gracias de nuevo!

  4. Aleman says:

    muy bueno el post!
    He tenido ese tipo de problemas con una galeria de imagenes de alta calidad.
    Lo resolví implementando dos listas. Mostraba las imagenes de baja calidad e implementaba como fondo de pantalla las imagenes que se seleccionaban de la galeria. Siempre liberando la memoria cada vez que se dejaba de usar.
    Es una solucion del estilo “parche”. Por supuesto que existen muchas soluciones mas eficientes…

  5. Brausoft says:

    Muy interesante el articulo.
    Gracias!!!

Leave a Reply

Your email address will not be published. Required fields are marked *