2009-12-22 7 views
29

Tengo algunas preguntas con respecto a objetos de mapa de bits y memoria y su taxonomía general.Bitmaps en Android

  1. ¿Qué es un mapa de bits en memoria o nativo?
  2. ¿En qué se diferencia la memoria de mapa de bits de la memoria Heap?

Respuesta

33

La memoria que realiza una copia de un objeto de mapa de bits se asigna el uso de código nativo (malloc()), en lugar de la palabra clave de Java new. Esto significa que la memoria es administrada directamente por el sistema operativo, en lugar de por Dalvik.

La única diferencia real entre el montón nativo y el montón de Dalvik es que el montón de Dalvik es basura, y el nativo no.

Sin embargo, para estos fines, aquí no hay mucha diferencia. Cuando su objeto Bitmap obtiene basura recolectada, su destructor reciclará la memoria asociada en el montón nativo.

Fuente:

+0

¿Sabes si este error alguna vez se solucionó? Actualmente me encuentro con el mismo problema en el trueno. Estoy reciclando los mapas de bits, pero nunca están despejando ningún espacio en el montón nativo que causan errores. –

+5

Solo para mayor claridad, la respuesta anterior es cierta para la versión 2.x de Android y a continuación. Comenzando con Android 3, las instancias de mapa de bits son contra el montón. Esto se puede verificar fácilmente: la creación de un mapa de bits en Android 2.x dejará prácticamente intacto el tamaño del almacenamiento dinámico Java, crearlo en Adnroid 3.x agregará muchos bytes al montón de Java. –

+0

¡Ah! Entonces, ¿estás diciendo que el recuento ahora es mucho más intuitivo? Eso es genial, excepto para todos los que escribimos código hacky para sumar el montón de Android con el montón nativo ... –

32

Hay una sutileza importante: a pesar de píxeles de mapa de bits se asignan en el montón nativo, algunos trucos especiales en Dalvik causa debe tenerse en cuenta frente al montón de Java. Esto se hace por dos razones:

(1) Para controlar la cantidad de memoria que una aplicación asigna. Sin la contabilidad, una aplicación podría asignar una gran cantidad de memoria (dado que el objeto Bitmap en sí mismo es muy pequeño pero puede retener una cantidad arbitrariamente grande de memoria nativa), extendiéndose más allá del límite de almacenamiento dinámico de 16MB o 24MB.

(2) Para ayudar a determinar cuándo a GC. Sin la contabilidad, podría asignar y liberar referencias en decir 100 objetos de mapa de bits; el GC no se ejecutaría, porque estos objetos son pequeños, pero de hecho podrían representar una gran cantidad de megabytes de asignaciones reales que ahora no están siendo sometidas a un GC de manera oportuna. Al contabilizar estas asignaciones contra el montón de Java, el recolector de elementos no utilizados se ejecutará cuando crea que se está utilizando la memoria.

Tenga en cuenta que de muchas maneras esto es un detalle de implementación; es muy probable que pueda cambiar en el futuro, aunque este comportamiento básico se mantendría de alguna forma, ya que estas son características importantes para gestionar las asignaciones de mapas de bits.

+1

Incluso en los teléfonos que cuentan mapas de bits contra el montón de Java, malloc nativo puede asignar MANERA más de 16 MiB. –

+10

El primer comentario es incorrecto, todos los teléfonos cuentan asignaciones de mapas de bits contra el límite de montón de Dalvik. El cambio principal a tener en cuenta es que, a partir de Android 3.0, las asignaciones se realizan realmente en el montón Dalvik, por lo que ya no tendrá que lidiar con situaciones en las que el GC no se ejecutará tan agresivamente como debería. – hackbod

+2

tienes razón en ese punto. Aún así, el GC se retarda cuando se trata de lidiar con bitmaps reciclados. He encontrado un comportamiento impredecible a menos que ejecute manualmente el GC después de reciclar un mapa de bits (incluida la tendencia a que la próxima "carga" devuelva una copia del mapa de bits reciclado en lugar de cargarlo realmente desde el disco) –

12

De despliegues en la naturaleza, he encontrado los siguientes dispositivos:

  • dispositivos que limitan a 16 MiB de almacenamiento dinámico de Java (mapas de bits son casi ilimitadas).
  • dispositivos que limitan a 16 MiB de (montón de Java + almacenamiento de mapa de bits nativo)
  • dispositivos que limitan a 24 MiB de almacenamiento dinámico de Java (mapas de bits son casi ilimitadas).
  • dispositivos que limitan a 24 MiB de (montón de Java + almacenamiento de mapa de bits nativo)

24 MiB tiende a ser los dispositivos de alta resolución, y se pueden detectar con Runtime.getRuntime() MaxMemory.(). También hay dispositivos de 32MiB ahora, y algunos de los teléfonos rooteados tienen 64Mib por defecto. Previamente, me confundí varias veces tratando de descubrir qué estaba pasando. Creo que todos los dispositivos cuentan los mapas de bits en el límite del montón. Pero es muy difícil hacer generalizaciones generalizadas sobre la flota de Android.

Este es un tema muy desagradable en Android, y muy confuso. Este límite y sus comportamientos están pobremente documentados, son complicados y extremadamente no intuitivos. También varían en los dispositivos y las versiones del sistema operativo, y tienen varios errores conocidos. Parte del problema es que los límites no son precisos: debido a la fragmentación del montón, alcanzará OOM mucho antes del límite real y debe dejar conservativamente un meg o dos de memoria intermedia. Peor aún, tengo varios dispositivos en los que hay una falla de segmentación nativa (100% un error en Android) que ocurre antes de que obtengas la excepción de OOM de Java, por lo que es doblemente importante no llegar nunca al límite ya que ni siquiera puedes atrapar el choque nativo. Para obtener más detalles sobre mis investigaciones, consulte this post. En la misma publicación, explico cómo medir el uso contra el límite y evitar bloqueos.

El tamaño del montón de Java es Runtime.getRuntime(). TotalMemory().

No hay una manera fácil de medir el tamaño del almacenamiento de mapa de bits nativo. El montón nativo general se puede medir con Debug.getNativeHeapAllocatedSize(), pero solo los mapas de bits cuentan hacia el límite (creo).

+0

Como cualquiera puede lanzar su propia versión de Android, parece bastante creíble que haya versiones que implementen diferentes políticas para limitar la memoria dinámica, incluidas las que usted describe anteriormente. CyanogenMod, por ejemplo, permite a los usuarios configurar el límite del montón por sí mismos, por lo que no veo por qué no podría haber una versión del sistema operativo que implemente las políticas relacionadas con los límites que usted describe. Me interesaría saber si existen directrices oficiales al respecto. De lo contrario, estamos sujetos a los caprichos de esas variantes de sistema operativo. – Carl

+0

@Carl.Por lo que puedo decir, es puro caos. Aunque, en general, los mods y los teléfonos rooteados tienden a aumentar los límites del montón, generalmente a 64M. La decisión de limitar tan severamente el tamaño del almacenamiento dinámico de Java fue un retraso cerebral y resulta en experiencias de usuario horribles. –

+0

Nos obliga como desarrolladores a examinar detenidamente nuestro uso de la memoria. Actualmente estoy desarrollando una aplicación que tiene un conjunto de datos muy grande que * debe * residir completamente en el montón (debido a un proceso de búsqueda intensivo), y mi implementación original basada en matrices de cadenas tomó 15 MB de capacidad solo para esos datos (cada referencia de cadena en la matriz toma 32 bytes de datos). Después de casi alcanzar el límite de 24 MB que todavía imponen muchos dispositivos actuales, diseñé una estructura de datos personalizada que toma solo 3.5MB para contener exactamente la misma información. Ahora mi aplicación se ejecutará incluso en un dispositivo con un límite de 16 MB. – Carl

-1

Podemos aumentar el tamaño del almacenamiento dinámico utilizando android:largeheap="true" en su archivo de manifiesto. Esto resolverá tu problema.

+0

Piensa en la batería de tus usuarios ... Solicitar una gran cantidad de datos para cubrir algunos errores en las asignaciones de memoria, claramente no puede ser una solución. – JuSchz

Cuestiones relacionadas