Skip to content

Most visited

Recently visited

navigation

Cómo explorar la memoria RAM usada

Cuando desarrolles apps para Android, siempre presta atención al consumo de memoria de acceso aleatorio (RAM) de tu app. Si bien durante los tiempos de ejecución de Dalvik y ART se realizan recolecciones de elementos no usados (GC) de rutina, debes comprender el momento y los puntos en que tu app asigna y libera memoria. Para proporcionar una experiencia de usuario estable en la cual el sistema operativo Android pueda alternar rápidamente entre diferentes apps, asegúrate de que tu app no necesariamente consuma memoria cuando el usuario no interactúe con ella.

Aun cuando apliques todas las prácticas recomendadas para administrar la memoria de tu app durante el desarrollo, es posible que se produzcan fugas de objetos o se introduzcan otros errores de memoria. La única forma de asegurarte de que tu app use la menor cantidad de memoria posible consiste en analizar el uso de memoria de tu app con las herramientas descritas aquí.

Interpretar mensajes de registro

Los mensajes de registro de tiempo de ejecución representan el punto más simple para comenzar a investigar el uso de memoria de tu app. A veces, cuando se produce una GC, puedes ver el mensaje en logcat.

Mensajes de registro de Dalvik

En Dalvik (pero no en ART), en cada GC se envía la siguiente información a logcat:

D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>

Ejemplo:

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms
Motivo de la GC
Qué desencadenó la GC y de qué tipo de recolección se trata. Entre los motivos que pueden aparecer, se incluyen los siguientes:
GC_CONCURRENT
Una GC simultánea que libera memoria a medida que el montón comienza a completarse.
GC_FOR_MALLOC
Se activó una GC porque tu app intentó asignar memoria cuando tu montón ya estaba completo, por lo cual el sistema debió detener tu app y recuperar memoria.
GC_HPROF_DUMP_HEAP
GC que se produce cuando solicitas la creación de un archivo HPROF para analizar tu montón.
GC_EXPLICIT
GC explícita que se produce, por ejemplo, cuando llamas a gc(); debes evitar este método y, en su lugar, permitir que la GC se ejecute cuando sea necesario.
GC_EXTERNAL_ALLOC
Esto sucede únicamente en el nivel de API 10 y en niveles inferiores (las versiones más nuevas realizan todas las asignaciones en el montón de Dalvik). Se trata de una GC para memoria asignada de manera externa (por ejemplo, los datos de píxeles almacenados en la memoria nativa o en búferes de bytes NIO).
Cantidad liberada
La cantidad de memoria recuperada a partir de esta GC.
Estadísticas del montón
Porcentaje libre del montón y (cantidad de objetos activos)/(tamaño total del montón).
Estadísticas de la memoria externa
Memoria asignada de manera externa en el nivel de API 10 y en niveles inferiores (cantidad de memoria asignada)/(límite en el que se producirá la recolección).
Tiempo de pausa
Los montones más grandes tendrán tiempos de pausa más prolongados. Los tiempos de pausa simultáneos presentan dos pausas: una al comienzo de la recolección y otra casi al final de esta.

Mientras se acumulan estos mensajes de registro, verifica si hay aumentos en las estadísticas del montón (valor 3571K/9991K del ejemplo anterior). Si este valor continúa aumentando, es posible que haya una fuga de memoria.

Mensajes de registro de ART

A diferencia de Dalvik, ART no registra mensajes para las GC que no se soliciten explícitamente. Las GC solo se registran cuando se considera que son lentas. Más precisamente, si la pausa de la GC supera los 5 ms o la duración de la GC supera los 100 ms. Si la app no se encuentra en un estado de proceso de pausa perceptible, ninguna de las GC se considera lenta. Las GC explícitas siempre se registran.

ART incluye la siguiente información en los mensajes de registro de recolección de elementos no usados:

I/art: <GC_Reason> <GC_Name> <Objects_freed>(<Size_freed>) AllocSpace Objects, <Large_objects_freed>(<Large_object_size_freed>) <Heap_stats> LOS objects, <Pause_time(s)>

Ejemplo:

I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects, 21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms
Motivo de la GC
Qué desencadenó la GC y de qué tipo de recolección se trata. Entre los motivos que pueden aparecer, se incluyen los siguientes:
Concurrent
GC simultánea que no suspende los subprocesos de la app. Esta GC se ejecuta en un subproceso en segundo plano y no evita que se realicen asignaciones.
Alloc
La GC se inició porque tu app intentó asignar memoria cuando tu montón ya estaba completo. En este caso, la recolección de elementos no usados tuvo lugar en el subproceso de asignación.
Explicit
La recolección de elementos no usados se activó como consecuencia de una solicitud explícita de una app (por ejemplo, llamando a gc() o gc()). Como sucede con Dalvik, en ART la mejor práctica consiste en confiar en la GC y evitar solicitar GC explícitas, si es posible. No se aconseja usar GC explícitas porque bloquean el subproceso de asignación y suponen un desperdicio innecesario de ciclos de CPU. También pueden ocasionar bloqueos (interrupción de flujo, inestabilidad o detenciones de la app) si impiden la activación de otros subprocesos.
NativeAlloc
La recolección se activó como consecuencia de la presión de la memoria nativa de las asignaciones nativas; por ejemplo, objetos de asignación RenderScript o mapas de bits.
CollectorTransition
La recolección se activó como consecuencia de una transición de montón. Esto se debe a la activación de la GC en tiempo de ejecución. Las transiciones del recolector consisten en copiar todos los objetos de un espacio respaldado por una lista libre a un espacio de puntero incremental (o viceversa). Actualmente, las transiciones del recolector solo ocurren cuando una app pasa de estados de proceso de pausa perceptible a un estado de no pausa perceptible (o viceversa) en dispositivos con poca memoria RAM.
HomogeneousSpaceCompact
La compactación espacial homogénea es una compactación de espacio de lista libre a espacio de lista libre que, por lo general, ocurre cuando una app pasa a un estado de proceso de pausa imperceptible. Se implementa principalmente para reducir el uso de memoria RAM y desfragmentar el montón.
DisableMovingGc
Esto no representa motivo real para una GC, pero sí un indicio de que la recolección se bloqueó debido al uso de GetPrimitiveArrayCritical durante la compactación de montón simultánea. En general, no se aconseja en absoluto usar GetPrimitiveArrayCritical debido a las restricciones que plantea para los recolectores móviles.
HeapTrim
Esto no representa un motivo para una GC, pero sí un indicio de que la recolección se bloqueó hasta que finalice una reducción de montón.
Nombre de la GC
ART presenta varias GC diferentes que pueden ejecutarse.
Concurrent mark sweep (CMS)
Recolector de montón completo que libera objetos y aplica recolección en todos los espacios, a excepción del de imágenes.
Concurrent partial mark sweep
Recolector de montón casi completo que aplica recolección en todos los espacios, a excepción de los espacios de imágenes y Zygote.
Concurrent sticky mark sweep
Recolector generacional que solo puede liberar objetos asignados desde la última GC. Esta recolección de elementos no usados se ejecuta con mayor frecuencia que un esquema “marcar y limpiar” total o parcial debido a que es más rápida y tiene pausas menos prolongadas.
Marksweep + semispace
Una GC de copia no simultánea que se usa para transiciones de montón y compactación espacial homogénea (para desfragmentar el montón).
Objetos liberados
Cantidad de objetos recuperados en esta GC del espacio de objetos pequeños.
Tamaño liberado
Cantidad de bytes recuperados en esta GC del espacio de objetos pequeños.
Objetos grandes liberados
Cantidad de objetos del espacio de objetos grandes recuperados de esta recolección de elementos no usados.
Tamaño de objetos grandes liberado
Cantidad de bytes del espacio de objetos grandes recuperados de esta recolección de elementos no usados.
Estadísticas del montón
Porcentaje libre y (cantidad de objetos activos)/(tamaño total del montón).
Tiempos de pausa
En general, los tiempos de pausa son proporcionales a la cantidad de referencias a objetos que se modificaron durante la GC. Actualmente, las GC de CMS de ART solo tienen una pausa, casi al final de la recolección. Las GC móviles tienen una pausa larga que se prolonga durante la mayor parte de dicha recolección.

Si observas una gran cantidad de GC en logcat, verifica si hay aumentos en las estadísticas del montón (valor 25MB/38MB del ejemplo anterior). Si este valor continúa aumentando y no parece disminuir, es posible que haya una fuga de memoria. De forma alternativa, si observas una GC con el motivo “Alloc”, significa que ya te encuentras operando cerca de la capacidad del montón y puedes esperar excepciones OOM pronto.

Acceder a Android Monitor

  1. Inicia tu app en un dispositivo o emulador conectado.
  2. Selecciona View > Tool Windows > Android Monitor.
  3. En la esquina superior izquierda de Android Monitor, selecciona la pestaña Monitors.

    Figura 1: Android Monitor y tres de sus monitores; Memory, CPU y GPU. En Android Studio, agranda el panel de Android Monitor en sentido vertical para ver el monitor Network.

Capturar un volcado de montón

Un volcado de montón es un resumen de todos los objetos del montón de tu app. El volcado de montón se almacena en un formato binario denominado HPROF que puedes cargar en una herramienta de análisis como jhat. El volcado del montón de tu app contiene información sobre el estado general del montón de tu app, por lo que puedes hacer un seguimiento de los problemas que puedes haber identificado durante la visualización de las actualizaciones de montón.

  1. En la parte superior del monitor Memory, haz clic en Dump Java Heap .

    Android Studio crea un archivo de resumen de montón con el nombre de archivo application-id_yyyy.mm.dd_hh.mm.hprof, abre el archivo en Android Studio y agrega el archivo a la lista Heap Snapshot de la pestaña Captures.

  2. En la pestaña Captures, haz clic con el botón secundario en el archivo y selecciona Export to standard .hprof.

Nota: Si necesitas ser más preciso sobre el momento en que se debe crear el volcado, puedes crear un volcado de montón en el punto crítico del código de tu app llamando a dumpHprofData().

Ver actualizaciones de montón

Usa Android Monitor para ver actualizaciones en tiempo real del montón de tu app mientras interactúas con esta. Las actualizaciones en tiempo real ofrecen información sobre la cantidad de memoria que se asigna para diferentes operaciones de la app. Puedes usar esta información para decidir si alguna operación usa demasiada memoria y necesita un ajuste para usar menos.

  1. Interactúa con tu app y, en el monitor Memory, observa la memoria Free y Allocated.
  2. Haz clic en Dump Java Heap .
  3. En la pestaña Captures, haz doble clic en el archivo de resumen de montón para abrir el visor de HPROF.
  4. Para activar la asignación del montón, interactúa con tu app y haz clic en Initiate GC .

Continúa interactuando con tu app e inicia diferentes GC. Observa la actualización de asignación de montón con cada GC. Identifica las acciones de tu app que generan demasiadas asignaciones y las áreas en las que podrías reducir las asignaciones y liberar recursos.

Analizar el volcado de montón

El volcado de montón se proporciona en un formato que es similar, pero no idéntico, al que ofrece la herramienta HPROF de Java. La principal diferencia en un volcado de montón de Android es que existe una gran cantidad de asignaciones en el proceso Zygote. Debido a que las asignaciones Zygote se comparten en todos los procesos de la app, no son muy importantes para tu propio análisis de montón.

Para analizar el volcado de montón, puedes usar una herramienta estándar como jhat. Para usar jhat, debes convertir el archivo HPROF del formato de Android al formato SE HPROF de Java. Para convertir el archivo al formato SE HPROF de Java, usa la herramienta hprof-conv que se ofrece en el directorio ANDROID_SDK/platform-tools/. Ejecuta el comando hprof-conv con dos argumentos: el archivo HPROF original y la ubicación para escribir el archivo HPROF convertido. Por ejemplo:

hprof-conv heap-original.hprof heap-converted.hprof

Puedes cargar el archivo convertido en una herramienta de análisis de montón que interprete el formato SE HPROF de Java. Durante el análisis, detecta fugas de memoria ocasionadas por alguno de los siguientes elementos:

  • Referencias duraderas a Activity, Context, View, Drawable y otros objetos que pueden hacer referencia al contenedor Activity o Context.
  • Clases internas no estáticas, como Runnable, que pueden contener una instancia Activity.
  • Cachés que almacenan objetos más tiempo del necesario.

Realizar un seguimiento de las asignaciones de memoria

El seguimiento de las asignaciones de memoria te permite comprender mejor el lugar donde se asignan los objetos que acaparan el uso de la memoria. Puedes usar el rastreador de asignaciones para analizar usos de memoria específicos y rutas de acceso de código críticas de una app, como el desplazamiento.

Por ejemplo, puedes usar el rastreador de asignaciones para hacer un seguimiento de las asignaciones mientras recorres (gesto fling) una lista en tu app. El seguimiento te permite ver todas las asignaciones de memoria necesarias para dicho comportamiento, el subproceso en el que se encuentran las asignaciones de memoria y el origen de estas. Este tipo de información puede ayudarte a optimizar las rutas de acceso de ejecución para reducir el trabajo que realizan, lo cual mejora el funcionamiento general de la app y la interfaz de usuario.

Si bien no es necesario o incluso posible quitar todas las asignaciones de memoria de las rutas de acceso de código críticas para el rendimiento, el rastreador de asignaciones puede ayudarte a identificar problemas importantes en tu código. Por ejemplo, una app puede crear un nuevo objeto Paint en cada trazado. Hacer que el código Paint sea global es una simple corrección que ayuda a mejorar el rendimiento.

  1. Inicia tu app en un dispositivo o emulador conectado.
  2. En Android Studio, selecciona View > Tool Windows > Android Monitor.
  3. En la esquina superior izquierda de Android Monitor, selecciona la pestaña Monitors.
  4. En la barra de herramientas del monitor de memoria, haz clic en rastreador de asignaciones para iniciar las asignaciones de memoria.
  5. Interactúa con tu app.
  6. Haz clic en rastreador de asignaciones nuevamente para detener el seguimiento de asignaciones.

    Android Studio crea un archivo de asignaciones con el nombre de archivo application-id_yyyy.mm.dd_hh.mm.alloc, lo abre en Android Studio y lo agrega a la lista Allocations de la pestaña Captures.

  7. En el archivo de asignaciones, identifica las acciones de tu app que pueden generar demasiadas asignaciones y determina el área de tu app en la que debes intentar reducir las asignaciones y liberar recursos.

Para obtener más información sobre el uso del rastreador de asignaciones, consulta Rastreador de asignaciones.

Ver asignaciones de memoria generales

Para un análisis más detallado, puedes observar la forma en que la memoria de tu app se divide entre diferentes tipos de asignaciones de memoria RAM con el siguiente comando adb:

adb shell dumpsys meminfo <package_name|pid> [-d]

El indicador “-d” ofrece más información relacionada con el uso de la memoria en Dalvik y ART.

Se muestra una lista de todas las asignaciones actuales de tu app, medidas en kilobytes.

Al inspeccionar esta información, debes estar familiarizado con los siguientes tipos de asignación:

RAM privada (sincronizada y no sincronizada)
Se trata de la memoria usada únicamente por tu proceso. Es el bloque de la memoria RAM que el sistema puede recuperar cuando se destruye el proceso de tu app. Por lo general, la parte más importante de esta es la memoria RAM privada no sincronizada; esta es la que más recursos consume porque solo la usa tu proceso y su contenido existe únicamente en formato RAM, por lo que no se puede paginar hacia almacenamiento (ya que Android no aplica intercambio). Todas las asignaciones de montón nativas y de Dalvik que hagas estarán relacionadas con la memoria RAM privada no sincronizada. Las asignaciones nativas y de Dalvik que compartes con el proceso Zygote representan la memoria RAM no sincronizada compartida.
Tamaño del conjunto proporcional (PSS)
Se trata de una medición del uso de memoria RAM de tu app en la que se tienen en cuenta las páginas compartidas entre diferentes procesos. Cualquier página de memoria RAM que sea exclusiva de tu proceso contribuye al valor de PSS de manera directa, mientras que las páginas que se comparten con otros procesos contribuyen a este valor solo de forma proporcional a la cantidad compartida. Por ejemplo, una página que se comparta entre dos procesos sumará la mitad de su tamaño al PSS de cada proceso.

Una característica interesante de la medición del PSS es que puedes sumar el valor de PSS de todos los procesos para determinar la memoria real que estos usan. Esto significa que el valor de PSS es un buen indicador del espacio de memoria RAM real que ocupa un proceso, y permite realizar comparaciones con respecto a la cantidad que usan otros procesos y la que se encuentra disponible en total.

A continuación, por ejemplo, se ofrece el resultado del proceso de visualización de mapas en un dispositivo Nexus 5. Existe mucha información aquí, pero los puntos de análisis claves se indican a continuación.

adb shell dumpsys meminfo com.google.android.apps.maps -d

Nota: La información que visualizas podría variar ligeramente con respecto a lo que se muestra aquí, debido a que algunos detalles del resultado difieren según la versión de la plataforma.

** MEMINFO in pid 18227 [com.google.android.apps.maps] **
                   Pss  Private  Private  Swapped     Heap     Heap     Heap
                 Total    Dirty    Clean    Dirty     Size    Alloc     Free
                ------   ------   ------   ------   ------   ------   ------
  Native Heap    10468    10408        0        0    20480    14462     6017
  Dalvik Heap    34340    33816        0        0    62436    53883     8553
 Dalvik Other      972      972        0        0
        Stack     1144     1144        0        0
      Gfx dev    35300    35300        0        0
    Other dev        5        0        4        0
     .so mmap     1943      504      188        0
    .apk mmap      598        0      136        0
    .ttf mmap      134        0       68        0
    .dex mmap     3908        0     3904        0
    .oat mmap     1344        0       56        0
    .art mmap     2037     1784       28        0
   Other mmap       30        4        0        0
   EGL mtrack    73072    73072        0        0
    GL mtrack    51044    51044        0        0
      Unknown      185      184        0        0
        TOTAL   216524   208232     4384        0    82916    68345    14570

 Dalvik Details
        .Heap     6568     6568        0        0
         .LOS    24771    24404        0        0
          .GC      500      500        0        0
    .JITCache      428      428        0        0
      .Zygote     1093      936        0        0
   .NonMoving     1908     1908        0        0
 .IndirectRef       44       44        0        0

 Objects
               Views:       90         ViewRootImpl:        1
         AppContexts:        4           Activities:        1
              Assets:        2        AssetManagers:        2
       Local Binders:       21        Proxy Binders:       28
       Parcel memory:       18         Parcel count:       74
    Death Recipients:        2      OpenSSL Sockets:        2

Aquí se muestra un dumpsys anterior sobre Dalvik de la app de Gmail:

** MEMINFO in pid 9953 [com.google.android.gm] **
                 Pss     Pss  Shared Private  Shared Private    Heap    Heap    Heap
               Total   Clean   Dirty   Dirty   Clean   Clean    Size   Alloc    Free
              ------  ------  ------  ------  ------  ------  ------  ------  ------
  Native Heap      0       0       0       0       0       0    7800    7637(6)  126
  Dalvik Heap   5110(3)    0    4136    4988(3)    0       0    9168    8958(6)  210
 Dalvik Other   2850       0    2684    2772       0       0
        Stack     36       0       8      36       0       0
       Cursor    136       0       0     136       0       0
       Ashmem     12       0      28       0       0       0
    Other dev    380       0      24     376       0       4
     .so mmap   5443(5) 1996    2584    2664(5) 5788    1996(5)
    .apk mmap    235      32       0       0    1252      32
    .ttf mmap     36      12       0       0      88      12
    .dex mmap   3019(5) 2148       0       0    8936    2148(5)
   Other mmap    107       0       8       8     324      68
      Unknown   6994(4)    0     252    6992(4)    0       0
        TOTAL  24358(1) 4188    9724   17972(2)16388    4260(2)16968   16595     336

 Objects
               Views:    426         ViewRootImpl:        3(8)
         AppContexts:      6(7)        Activities:        2(7)
              Assets:      2        AssetManagers:        2
       Local Binders:     64        Proxy Binders:       34
    Death Recipients:      0
     OpenSSL Sockets:      1

 SQL
         MEMORY_USED:   1739
  PAGECACHE_OVERFLOW:   1164          MALLOC_SIZE:       62

En general, concéntrate solo en las columnas Pss Total y Private Dirty. En algunos casos, en las columnas Private Clean y Heap Alloc también ofrecen datos interesantes. A continuación, se presenta más información sobre las diferentes asignaciones de memoria (filas) que debes observar:

Dalvik Heap
RAM que usan las asignaciones de Dalvik en tu app. En la columna Pss Total se incluyen todas las asignaciones del proceso Zygote (ponderadas por el uso compartido de estas entre los procesos, como se describe en la definición de PSS antes presentada). El número de la columna Private Dirty representa la memoria RAM real destinada únicamente al montón de tu app, compuesto por tus propias asignaciones y cualquier página de asignación Zygote que se haya modificado desde la bifurcación del proceso de tu app desde Zygote.

Nota: En las versiones de plataforma más nuevas que tienen la sección Dalvik Other, los números Pss Total y Private Dirty para el montón de Dalvik no incluyen la sobrecarga de Dalvik, como la compilación justo a tiempo (JIT) y el registro de GC, mientras que las versiones anteriores incluyen una lista combinada de esta información en Dalvik.

Heap Alloc es la cantidad de memoria de la cual hacen un seguimiento los asignadores de montón nativo y de Dalvik para tu app. Este valor es superior a Pss Total y Private Dirty porque tu proceso se bifurcó desde Zygote e incluye asignaciones que tu proceso comparte con los demás.

.so mmap y .dex mmap
Memoria RAM que se usa para código asignado .so (nativo) y .dex (Dalvik o ART). El número Pss Total incluye el código de la plataforma que se comparte entre las apps. Private Clean representa el código propio de tu app. Por lo general, el tamaño asignado real será mucho mayor: aquí, la memoria RAM incluye solo lo que actualmente debe estar en ella para código ejecutado por la app. Sin embargo, .so mmap presenta una memoria RAM privada no sincronizada de tamaño amplio. Esto se debe a correcciones en el código nativo que se realizaron cuando se cargó en su dirección final.
.oat mmap
Cantidad de memoria RAM usada por la imagen de código que se basa en las clases previamente cargadas, comúnmente empleadas por varias apps. Esta imagen se comparte entre todas las apps y no se ve afectada por apps específicas.
.art mmap
Cantidad de memoria RAM usada por la imagen del montón que se basa en las clases previamente cargadas, comúnmente empleadas por varias apps. Esta imagen se comparte entre todas las apps y no se ve afectada por apps específicas. Si bien la imagen de ART contiene instancias de Object, no se tiene en cuenta para calcular el tamaño de montón.
.Heap (únicamente con indicador -d)
Cantidad de memoria de montón para tu app. Se excluyen objetos de los espacios de objetos grandes e imágenes, pero se incluyen el espacio Zygote y el espacio fijo.
.LOS (únicamente con indicador -d)
Cantidad de memoria RAM usada por el espacio de objetos grandes de ART. Se incluyen los objetos grandes de Zygote. Todos los objetos grandes son asignaciones primitivas de matrices superiores a 12 KB.
.GC (únicamente con indicador -d)
Cantidad de sobrecarga interna de contabilización de GC para tu app. No es posible reducir esta sobrecarga.
.JITCache (únicamente con indicador -d)
Cantidad de memoria usada por los cachés de código y datos de JIT. Comúnmente, es un valor de cero debido a que todas las apps se compilarán en el momento de la instalación.
.Zygote (únicamente con indicador -d)
Se trata de la cantidad de memoria usada por el espacio de Zygote. Dicho espacio se crea durante el arranque del dispositivo y en él nunca se realizan asignaciones.
.NonMoving (únicamente con indicador -d)
Cantidad de memoria RAM usada por el espacio fijo de ART. Dicho espacio contiene objetos no movibles especiales, como campos y métodos. Puedes reducir esta sección usando menos campos y métodos en tu app.
.IndirectRef (únicamente con indicador -d)
Cantidad de memoria RAM usada por las tablas de referencia indirecta de ART. Por lo general, esta cantidad es pequeña. Sin embargo, si es demasiado grande se puede reducir mediante reduciendo la cantidad de referencias JNI globales y locales que se usan.
Unknown
Cualquier página de memoria RAM que el sistema no pudo clasificar en uno de los demás elementos más específicos. Actualmente, contiene asignaciones que por lo general son nativas y que la herramienta no puede identificar durante la recolección de estos datos, debido a la selección aleatoria del diseño del espacio de direcciones (ASLR). Como sucede con el montón de Dalvik, el valor de Pss Total para Unknown tiene en cuenta las páginas compartidas con Zygote, y Private Dirty es la memoria RAM desconocida dedicada únicamente a tu app.
TOTAL
Memoria RAM total de tamaño del conjunto proporcional (PSS) que usa tu proceso. Es la suma de todos los campos PSS que se hallan encima de este. Indica el espacio total de la memoria que ocupa tu proceso, que se puede comparar directamente con la de otros procesos y la memoria RAM disponible en total.

Private Dirty y Private Clean son las asignaciones totales dentro de tu proceso, que no se comparten con otros procesos. Juntas (en especial Private Dirty), representan la cantidad de memoria RAM que se enviará nuevamente al sistema cuando se destruya tu proceso. La memoria RAM no sincronizada hace referencia a páginas que se han modificado y que, por lo tanto, deben permanecer dedicadas a la memoria RAM (porque no hay intercambio). La memoria RAM sincronizada representa páginas asignadas desde un archivo persistente (por ejemplo, el código que se ejecuta) y que, por lo tanto, se pueden paginar si no se usan durante un tiempo.

ViewRootImpl
Cantidad de vistas raíz activas en tu proceso. Cada vista raíz está asociada a una ventana, de modo que esto puede ayudarte a identificar fugas de memoria relacionadas con cuadros de diálogos u otras ventanas.
AppContexts y Activities
Cantidad de objetos Context y Activity de la app actualmente activos en tu proceso. Esto puede ayudarte a identificar rápidamente objetos Activity fugados que no estén sujetos a la recolección de elementos no usados debido a referencias estáticas sobre ellos, lo cual es común. A menudo, estos objetos tienen muchas otras asignaciones asociadas a ellos, lo cual los convierte en un buen elemento para realizar un seguimiento de fugas de memoria de gran envergadura.

Nota: Un objeto View o Drawable también hace referencia a la Activity de la que proviene. Por ello, conservar un objeto View o Drawable también puede hacer que tu app presente una fuga de Activity.

Desencadenar fugas de memoria

Al usar las herramientas descritas anteriormente, debes imponer de manera agresiva 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. Las fugas se desplazarán 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:

  1. 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 ocasionar la fuga de un objeto Activity, Context o View porque el sistema recrea la Activity, y si tu app conserva una referencia a uno de dichos objetos en algún otro lugar el sistema no puede incluirlo en la recolección de elementos no usados.
  2. Alterna entre tu app y otra en diferentes estados de actividad (navega hasta la pantalla principal y luego regresa a tu app).

Sugerencia: También puedes realizar los pasos anteriores usando el framework de prueba monkey. Para obtener más información sobre cómo ejecutar el framework de prueba monkey, lee la documentación de monkeyrunner.

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience.
(Sep 2017 survey)