Tengo una excepción OutOfMemory con una galería de más de 600x800 píxeles JPEG.Android: OutofMemoryError: el tamaño del mapa de bits excede el presupuesto de VM sin ningún motivo. Puedo ver
El entorno
He estado usando la galería con las imágenes JPG alrededor de 600x800 píxeles.
Dado que mi contenido puede ser un poco más complejo que las imágenes, he configurado cada vista como una RelativeLayout que envuelve ImageView con el JPG.
Para "acelerar" la experiencia del usuario Tengo un caché simple de 4 ranuras que precaptura (en un looper) aproximadamente 1 imagen a la izquierda y 1 imagen a la imagen mostrada y las mantiene en un mapa HashMap de 4.
La plataforma
estoy usando AVD de 256 RAM y 128 Montón tamaño, con una pantalla de 600x800. También ocurre en un destino Entourage Edge, excepto que con el dispositivo es más difícil de depurar.
El problema
He estado recibiendo una excepción:
OutofMemoryError: bitmap size exceeds VM budget
Y sucede cuando ir a buscar la quinta imagen. Intenté cambiar el tamaño de la memoria caché de mi imagen, y sigue siendo la misma.
Lo extraño: No debería ser un problema de memoria
Con el fin de asegurarse de que el límite de montón es muy lejos de lo que necesito, he definido un conjunto de 8 MB maniquí en el comenzando, y lo dejó sin referencia, por lo que se envía de inmediato. Es un miembro de la rosca actividad y se define como siguiente
static { @SuppressWarnings("unused")
byte dummy[] = new byte[ 8*1024*1024 ]; }
El resultado es que el tamaño del montón es casi 11MB y todo es gratis. Nota He agregado ese truco después de que comenzó a fallar. Hace que OutOfMemory sea menos frecuente.
Ahora, estoy usando DDMS. Justo antes del accidente (no cambia mucho después del accidente), DDMS muestra:
ID Heap Size Allocated Free %Used #Objects
1 11.195 MB 2.428 MB 8.767 MB 21.69% 47,156
Y en la tabla de detalle que muestra:
Type Count Total Size Smallest Largest Median Average
free 1,536 8.739MB 16B 7.750MB 24B 5.825KB
El bloque más grande es 7.7MB. Sin embargo, el LogCat dice:
ERROR/dalvikvm-heap(1923): 925200-byte external allocation too large for this process.
Si te importa la relación entre la mediana y la media, es plausible suponer que la mayoría de los bloques disponibles son muy pequeñas. Sin embargo, hay un bloque lo suficientemente grande para el mapa de bits, es 7.7M. ¿Cómo es que todavía no es suficiente?
Nota: Grabé una línea de pila. Al observar la cantidad de datos asignados, no parece que se hayan asignado más de 2M. Coincide con el informe de memoria libre por DDMS.
- Podría ser que lo experimentan algún problema como el de lixiviación en la fragmentación?
- ¿Cómo resuelvo/soluciono el problema?
- ¿El montón se comparte con todos los hilos?
- ¿Podría ser que interprete la lectura DDMS de una manera incorrecta, y realmente no hay un bloque 900K para asignar? Si es así, ¿alguien puede decirme dónde puedo ver eso?
Muchas gracias
Meymann
Puede obtener algunas picaduras aquí si publica el código que realmente está buscando/decodificando/almacenando en caché/expirando los mapas de bits. El problema es casi seguro que es lo que está haciendo allí, no algo que requiera profundizar en el funcionamiento interno de la asignación del montón. –
Al depurar código, mi principal sospechoso es siempre mi código. Para depurarlo, obtengo sugerencias del entorno. Desafortunadamente, en este caso: A. crear un código simple que lea 3 imágenes de 600x800 a la vez en un caché arrojaría resultados similares de forma esporádica (marcada para hacer que suceda más rápido, se pueden agregar matrices sin referencias ficticias), B. Utilizo las herramientas para investigar el problema, pero las sugerencias que recibo de las herramientas no coinciden. C. El objetivo de esta pregunta es obtener indicios de qué es una buena práctica, qué está mal con mis conclusiones sobre la lectura de DDMS, y si hay una solución alternativa. – Meymann
** Una manera muy fácil de reproducir el problema en otra forma ** 1. en su clase de Actividad, agregue estático {byte dummy [] = new byte [4096]; } forzar al montón a expandirse (y eliminar dudas). 2. crea un ViewFlipper. 3. Agregue aproximadamente 10 ImageView donde cada uno se refiere a un mapa de bits 600x800 dibujable. 4. Cuando falla, mira el DDMS. – Meymann