Registrar las asignaciones de Java o Kotlin te ayuda a identificar patrones de memoria no deseados que podrían estar causando problemas de rendimiento. El generador de perfiles puede mostrarte lo siguiente sobre la asignación de objetos:
- Qué tipos se asignaron y cuánto espacio ocupan
- El seguimiento de pila de cada asignación, incluido el subproceso
- Cuándo se desasignaron los objetos
Registrar asignaciones de memoria durante interacciones normales e intensivas del usuario para determinar con exactitud si tu código asigna demasiados objetos en poco tiempo o si asigna objetos que se fugan Obtén más información sobre por qué debes generar perfiles para la memoria de tu app.
Cómo grabar asignaciones de Java o Kotlin
Para registrar asignaciones de Java o Kotlin, selecciona la tarea Track Memory Consumption (Java/Kotlin Allocations) en la pestaña Home del generador de perfiles. Ten en cuenta que necesitas una app depurable (usa Profiler: run 'app' as debuggable (complete data)) para registrar asignaciones de Java o Kotlin.
De forma predeterminada, Android Studio captura todas las asignaciones de objetos en la memoria. Si tu app asigna una gran cantidad de objetos, es posible que se produzcan ralentizaciones visibles en ella durante la generación de perfiles. Para mejorar el rendimiento durante la generación de perfiles, ve al menú desplegable Allocation Tracking y selecciona Sampled en lugar de Full. Cuando se realiza un muestreo, el generador de perfiles recopila las asignaciones de objetos en la memoria a intervalos regulares.
Para forzar un evento de recolección de elementos no utilizados durante la grabación, haz clic en el ícono de papelera
.
Descripción general de las asignaciones de Java/Kotlin
Después de detener la grabación, verás lo siguiente:
- El cronograma de eventos muestra los estados de actividad, los eventos de entrada del usuario y los eventos de rotación de pantalla.
- En el cronograma de uso de memoria, se muestra la siguiente información. Selecciona una parte del cronograma para filtrar por un período determinado.
- Un gráfico de barras apiladas del volumen de memoria que se usa en cada categoría, como se indica con el eje Y a la izquierda, y la clave de color en la parte superior
- Una línea punteada que indica la cantidad de objetos asignados, como se indica con el eje Y a la derecha
- Un ícono para cada evento de recolección de elementos no utilizados
- En la pestaña Tabla, se muestra una lista de clases. El Total Count es la cantidad de asignaciones al final del intervalo de tiempo seleccionado (Allocations menos Deallocations), por lo que podría ser conveniente depurar primero las clases que tienen los valores de Total Count más altos. Si te interesa más solucionar problemas de clases según las asignaciones máximas durante el período seleccionado, prioriza por Asignaciones. De manera similar, el Remaining Size es el Allocations Size menos el Deallocations Size en bytes.
- Cuando haces clic en una clase de la lista Table, se abre el panel Instance con una lista de objetos asociados, que incluye cuándo se asignaron, cuándo se desasignaron y su tamaño aplanado.
En la pestaña Visualización, se muestra una vista agregada de todos los objetos de la pila de llamadas durante el período seleccionado. Básicamente, te muestra cuánta memoria total ocupa la pila de llamadas con las instancias que se muestran. En la primera fila, se muestra el nombre del subproceso. De forma predeterminada, los objetos se apilan de izquierda a derecha según el tamaño de asignación. Usa el menú desplegable para cambiar el orden.

Usa el menú desplegable de montones para filtrar por montones específicos. Además de los filtros disponibles cuando capturas un volcado de montón, puedes filtrar por clases en el montón de JNI, que muestra dónde se asignan y liberan las referencias de la interfaz nativa de Java (JNI).
Usa el menú desplegable de organización para elegir cómo organizar las asignaciones. Además de las disposiciones disponibles cuando capturas un volcado de montón, puedes organizar por pila de llamadas.
Cómo se registra la memoria
Los números que ves en la parte superior se basan en todas las páginas privadas de memoria que confirma tu app, según el sistema Android. Este registro no incluye páginas compartidas con el sistema ni otras apps. Las categorías del recuento de memoria son las siguientes:
- Java: Es la memoria de objetos asignados desde código Java o Kotlin.
Nativa: Es la memoria de objetos asignados desde código C o C++.
Incluso si no usas C++ en tu app, puedes ver memoria nativa usada aquí porque el framework de Android utiliza ese tipo de memoria para administrar varias tareas por ti; por ejemplo, cuando maneja recursos de imagen y otros gráficos (aunque tu código esté en Java o Kotlin).
Gráficos: Es la memoria usada para colas de búfer de gráficos con el propósito de mostrar píxeles en la pantalla, incluidas las superficies y texturas GL, entre otras opciones. Ten en cuenta que se trata de memoria compartida con la CPU, y no de memoria dedicada de la GPU.
Pila: Es la memoria usada tanto por las pilas nativas como por las de Java en tu app. Esto normalmente se relaciona con la cantidad de subprocesos en ejecución que tiene tu app.
Código: Es la memoria que tu app usa para código y recursos, como código de bytes DEX, código DEX optimizado o compilado, bibliotecas .so y fuentes.bibliotecas de
soy fuentes.Otras: Esta categoría incluye la memoria usada por tu app que el sistema no sabe cómo categorizar.
Asignada: Es la cantidad de objetos Java y Kotlin asignados por tu app. No se tienen en cuenta los objetos asignados en C o C++.
Inspecciona el registro de asignación
Para inspeccionar el registro de asignaciones, sigue estos pasos:
- Explora la lista de clases en la pestaña Table para encontrar objetos que tengan valores inusualmente grandes de Allocations o Total Count (según lo que estés optimizando) y que podrían experimentar fugas.
- En el panel Instance View, haz clic en una instancia. Según lo que corresponda a esa instancia, se abrirá la pestaña Fields o Pila de llamadas de asignación. Usa la información de las pestañas Fields o Allocation Call Stack para determinar si las instancias son realmente necesarias o si son duplicaciones innecesarias.
Haz clic con el botón derecho en cualquier entrada de la lista para ir al código fuente correspondiente.
Cómo ver referencias globales de JNI
La interfaz nativa de Java (JNI) es un framework que permite que se llamen entre sí el código Java y el código nativo. Las referencias de JNI se administran manualmente con código nativo, por lo que es posible que se produzcan problemas como los siguientes:
- Los objetos Java que usa el código nativo se mantienen activos durante demasiado tiempo.
- Algunos objetos del montón de Java pueden llegar a ser inalcanzables si se descarta una referencia de JNI sin primero borrarla de forma explícita.
- Se agotó el límite de referencias globales de JNI.
Para solucionar problemas de este tipo, selecciona View JNI heap en el generador de perfiles para examinar todas las referencias globales de JNI y filtrarlas por tipos de Java y pilas de llamadas nativas. Haz clic con el botón derecho en un campo de instancia de la pestaña Fields y selecciona Go to instance para ver la pila de llamadas de asignación correspondiente.
La pestaña Allocation Call Stack muestra dónde se asignan y se liberan las referencias de JNI en tu código.
Para obtener más información sobre JNI, consulta estas sugerencias relacionadas.