Captura un volcado de montón para ver qué objetos de tu app consumen memoria en el momento de la captura y para identificar fugas de memoria o el comportamiento de asignación de memoria que genera inestabilidades, fallas e incluso bloqueos de la app. Es especialmente útil tomar volcados de montón después de una sesión de usuario extendida, cuando podría mostrar objetos que todavía están en la memoria y que ya no deberían estar ahí.
En esta página, se describen las herramientas que proporciona Android Studio para recopilar y analizar volcados de montón. Como alternativa, puedes inspeccionar la memoria de tu app desde la línea de comandos con dumpsys
y también ver eventos de recolección de elementos no utilizados (GC) en Logcat.
Por qué debes generar perfiles para la memoria de tu app
Android proporciona un entorno de memoria administrada. Cuando Android determina que tu app ya no usa algunos objetos, el recolector de elementos no utilizados libera la memoria que no se usó para devolverla al montón. La forma en la que Android busca memoria sin usar se somete a optimizaciones constantes. Sin embargo, en algún punto de todas las versiones de Android, el sistema debe pausar brevemente tu código. La mayoría de las veces, las pausas son imperceptibles. Sin embargo, si tu app asigna memoria a una velocidad que supera la que el sistema es capaz de alcanzar para recolectarla, tu app puede experimentar una demora mientras el recopilador libera suficiente memoria para satisfacer tus asignaciones. La demora podría hacer que tu app omitiera fotogramas y causara una lentitud visible.
Aunque tu app no muestre lentitud, si tiene fugas de memoria, puede retener esa memoria incluso mientras se encuentre en segundo plano. Este comportamiento puede desacelerar el rendimiento del resto de la memoria del sistema forzando eventos innecesarios de recolección de elementos no utilizados. Finalmente, el sistema se ve forzado a finalizar el proceso de tu app para recuperar la memoria. Luego, cuando el usuario regresa a la app, el proceso de la app debe reiniciarse por completo.
Para obtener más información sobre prácticas de programación que pueden reducir el uso de memoria de tu app, consulta Cómo administrar la memoria de tu app.
Descripción general del volcado de montón
Para capturar un volcado de montón, selecciona la tarea Analyze Memory Usage (Heap Dump) (usa Profiler: run 'app' as debuggable (complete data)) para capturar un volcado de montón. Mientras se vuelca el montón, es posible que aumente de forma temporal el volumen de la memoria Java. Esto es normal, ya que el volcado de montón ocurre en el mismo proceso que tu app y requiere memoria para recolectar datos. Después de capturar el volcado de montón, verás lo siguiente:
En la lista de clases, se muestra la siguiente información:
- Allocations: muestra la cantidad de asignaciones que contiene el montón.
Native Size: Es la cantidad total (en bytes) de memoria nativa que utiliza este tipo de objeto. Aquí, verás la memoria de algunos objetos asignados en Java debido a que Android usa memoria nativa para algunas clases de frameworks, como
Bitmap
.Shallow Size: Es la cantidad total (en bytes) de memoria Java que utiliza este tipo de objeto.
Retained Size: Es el tamaño total (en bytes) de la memoria retenida debido a todas las instancias de esta clase.
Usa el menú del montón para filtrar ciertos montones:
- Montón de la app (predeterminado): Es el montón principal en el que asigna memoria tu app.
- Montón de imágenes: Es la imagen de inicio del sistema, que contiene clases precargadas durante ese período. Las asignaciones aquí nunca se mueven ni desaparecen.
- Zygote heap: Es el montón de copia en escritura en el que se bifurca un proceso de la app en el sistema Android.
Usa el menú desplegable de organización para elegir cómo organizar las asignaciones:
- Arrange by class (default): Agrupa todas las asignaciones según el nombre de la clase.
- Arrange by package: Agrupa todas las asignaciones según el nombre del paquete.
Usa el menú desplegable de clases para filtrar grupos de clases:
- Todas las clases (predeterminada): Muestra todas las clases, incluidas las de las bibliotecas y dependencias.
- Show activity/fragment leaks: Muestra las clases que causan fugas de memoria.
- Show project classes: Muestra solo las clases definidas por tu proyecto.
Haz clic en el nombre de una clase para abrir el panel Instance. Cada instancia que se muestra incluye lo siguiente:
- Depth: es el menor número de saltos desde cualquier raíz de recolección de elementos no utilizados a la instancia seleccionada.
- Native Size: Es el volumen de esta instancia en la memoria nativa. Esta columna solo se ve en Android 7.0 y versiones posteriores.
- Shallow Size: Volumen de esta instancia en la memoria Java.
- Retained Size: Es el volumen de memoria que domina esta instancia (de acuerdo con el árbol de dominadores).
Haz clic en una instancia para mostrar los detalles de la instancia, incluidos sus campos y referencias. Los tipos de campo y referencia comunes son los tipos estructurados , los arrays y los tipos de datos primitivos en Java. Haz clic con el botón derecho en un campo o una referencia para ir a la instancia o línea asociada en el código fuente.
- Campos: Muestra todos los campos de esta instancia.
- Referencias: Muestra todas las referencias al objeto destacado en la pestaña Instancia.
Cómo encontrar fugas de memoria
Para filtrar rápidamente las clases que podrían estar asociadas con fugas de memoria, abre el menú desplegable de la clase y selecciona Show activity/fragment leaks. Android Studio muestra clases que considera que indican pérdidas de memoria para instancias de Activity
y Fragment
en tu app. Los tipos de datos que muestra el filtro incluyen los siguientes:
- Instancias
Activity
que se destruyeron, pero a las que todavía se hace referencia. - Instancias
Fragment
que no tienen unFragmentManager
válido, pero a las que aún se hace referencia
Ten en cuenta que el filtro puede generar falsos positivos en las siguientes situaciones:
- Se creó un
Fragment
, pero todavía no se usó. - Se almacena en caché un
Fragment
, pero no como parte de unFragmentTransaction
.
Para buscar fugas de memoria de forma más manual, explora las listas de clases e instancias para encontrar objetos con un tamaño retenido grande. Busca fugas de memoria ocasionadas por alguno de los siguientes elementos:
- Referencias duraderas a
Activity
,Context
,View
,Drawable
y otros objetos que pueden contener una referencia al contenedorActivity
oContext
- Clases internas no estáticas, como
Runnable
, que pueden contener una instanciaActivity
. - Cachés que almacenan objetos más tiempo del necesario
Cuando encuentres posibles fugas de memoria, usa las pestañas Campos y Referencias en Detalles de la instancia para ir a la instancia o línea de código fuente de interés.
Cómo activar fugas de memoria para pruebas
Para analizar el uso de la memoria, debes forzar el código de tu app e intentar forzar fugas de memoria. Una forma de provocar fugas de memoria en tu app es permitir que esta se ejecute durante un rato antes de inspeccionar el montón. Es posible que las fugas se desplacen hasta la parte superior de las asignaciones en el montón. Sin embargo, cuanto más pequeña sea la fuga, durante más tiempo deberás ejecutar la app para poder verla.
También puedes activar una fuga de memoria de una de las siguientes maneras:
- Gira el dispositivo de la posición vertical a la horizontal y repite ese movimiento varias veces en diferentes estados de actividad. A menudo, la rotación del dispositivo puede hacer que en una app se produzca la fuga de un objeto
Activity
,Context
oView
debido a que el sistema recrea laActivity
, y si tu app conserva una referencia a uno de esos objetos en otro lugar, el sistema no puede incluirlo en la recolección de elementos no utilizados. - Alterna entre tu app y otra en diferentes estados de actividad. Por ejemplo, navega a la pantalla principal y, luego, regresa a la app.
Cómo exportar e importar una grabación de volcado de montón
Puedes exportar e importar un archivo de volcado de montón desde la pestaña Grabaciones anteriores del generador de perfiles. Android Studio guarda la grabación como un archivo .hprof
.
Como alternativa, para usar un analizador de archivos .hprof
diferente, como jhat, debes convertir el archivo .hprof
del formato de Android al formato de archivo .hprof
de Java SE. Para convertir el formato de archivo, usa la herramienta hprof-conv
que se proporciona en el directorio {android_sdk}/platform-tools/
. Ejecuta el comando hprof-conv
con dos argumentos: el nombre de archivo .hprof
original y la ubicación para escribir el archivo .hprof
convertido, incluido el nuevo nombre de archivo .hprof
. Por ejemplo:
hprof-conv heap-original.hprof heap-converted.hprof