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 comportamientos de asignación de memoria que provocan tartamudeos, bloqueos e, incluso, fallas de la app. Es especialmente útil tomar volcados de montón después de una sesión de usuario extensa, cuando podría mostrar objetos que todavía están en la memoria y que ya no deberían estar allí.
En esta página, se describe la herramienta 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 a la pila. 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 recolector libera suficiente memoria para satisfacer tus asignaciones. La demora podría hacer que tu app omitiera marcos 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, el volumen de memoria Java puede aumentar temporalmente. 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.
Tamaño nativo: 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 marcos de trabajo, como
Bitmap.Shallow Size: es la cantidad total (en bytes) de memoria Java que utiliza este tipo de objeto.
Tamaño retenido: es el tamaño total (en bytes) de la memoria retenida debido a todas las instancias de esta clase.
Usa el menú de montón para filtrar a ciertos montones:
- Montón de la app (predeterminado): es el montón principal en el que asigna memoria tu app.
- Image heap: La imagen de arranque del sistema, que contiene clases precargadas durante el arranque. 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 disposició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 clase para filtrar a grupos de clases:
- Todas las clases (predeterminado): Muestra todas las clases, incluidas las de 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 un nombre de clase para abrir el panel Instance. Cada instancia listada incluye lo siguiente:
- Profundidad: 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: Volumen de memoria que domina esta instancia (de acuerdo con el árbol de dominadores).
Haz clic en una instancia para mostrar los Instance Details, incluidos sus Fields
y References. Los tipos de campos y referencias comunes son tipos estructurados
,
arrays
,
y 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.
- Fields: Muestra todos los campos de esta instancia.
- Referencias: Muestra todas las referencias al objeto destacado en la pestaña Instance.
Cómo encontrar fugas de memoria
Para filtrar rápidamente a las clases que podrían estar asociadas con fugas de memoria, abre el menú desplegable de clase y selecciona Show activity/fragment leaks. Android Studio
muestra las clases que cree que indican fugas de memoria para
Activity y
Fragment instancias en tu app.
Para buscar fugas de memoria de forma más manual, explora las listas de clases y de instancias para encontrar objetos con un Retained Size grande. Busca fugas de memoria ocasionadas por alguno de los siguientes elementos:
- Referencias de larga duración a
ActivityoContextque pueden filtrar el gráfico de composición de Compose alojado (comoComposeViewy sus elementos componibles secundarios) - Fugas de objetos de estado de Jetpack Compose (
MutableState), titulares de estado o lambdas que capturanContext - Olvidar limpiar objetos de escucha o observadores en el
onDisposebloque de unDisposableEffect. - Clases internas no estáticas, como a
Runnable, que pueden contener unaActivityinstancia. - Cachés que almacenan objetos más tiempo del necesario
Cuando encuentres posibles fugas de memoria, usa las pestañas Fields y References en Instance Details para saltar a la instancia o línea de código fuente de interés.
Cómo activar fugas de memoria para realizar pruebas
Para analizar el uso de la memoria, debes forzar el código de tu app e intentar que se produzcan fugas de memoria. Para ello, puedes permitir que se ejecute tu app 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. Girar el dispositivo a menudo puede hacer que una app
filtre una
Activity(y, por lo tanto, su árbol de IU de Compose alojado y los árboles de estado asociados) si tu app tiene una referencia a laActivityoContextdentro de operaciones asíncronas o titulares de estado. - Alterna tu app y otra en diferentes estados de la actividad. Por ejemplo, navega hasta la pantalla principal y, luego, regresa a tu 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 Past Recordings en el 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