2009-09-07 10 views
6

Estoy escribiendo un MIDlet usando LWUIT y parece que las imágenes consumen cantidades increíbles de memoria. Todas las imágenes que uso son PNG y están empaquetadas dentro del archivo JAR. Los cargo usando el método estándar Image.createImage (URL). La aplicación tiene varios formularios y cada uno tiene un par de etiquetas y botones, sin embargo, estoy bastante seguro de que solo la forma activa se mantiene en la memoria (sé que no es muy confiable, pero Runtime.freeMemory() parece confirmar esta).Las imágenes JavaME - LWUIT consumen toda la memoria

La aplicación ha funcionado bien en una resolución de 240x320, pero al moverla a 480x640 y al usar imágenes de mayor tamaño para la IU comenzó a aparecer errores de memoria insuficiente. Lo que hace la aplicación, entre otras cosas, es descargar imágenes remotas. La aplicación parece funcionar bien hasta que llega a este punto. Después de descargar un par de PNG y regresar al menú principal, se encuentra el error de falta de memoria. Naturalmente, investigué la cantidad de memoria que usa el menú principal y fue bastante impactante. Solo son dos etiquetas con imágenes y cuatro botones. Cada botón tiene tres imágenes utilizadas para style.setIcon, setPressedIcon y setRolloverIcon. Las imágenes varían en tamaño de 15 a 25 KB, pero la eliminación de dos de las tres imágenes utilizadas para cada botón (8 imágenes en total), Runtime.freeMemory() mostró una impresionante disminución de 1 MB en el uso de la memoria.

La forma en que lo veo, o tengo un montón de fugas de memoria (que no creo que haga, pero las fugas de memoria no se sabe exactamente que se rastrean fácilmente), estoy haciendo algo terriblemente mal con manejo de imágenes o realmente no hay ningún problema involucrado y solo necesito reducir la escala.

Si alguien tiene alguna idea que ofrecer, le agradecería muchísimo.

+1

una solución sino un tipp:.. optimizar su png con OptiPNG (http://optipng.sourceforge.net/) - cortes imágenes con una pequeña cantidad de colores a menudo hasta el 50% de su tamaño sin reducción de la calidad. – user181750

Respuesta

0

¿Pensó en el hecho de que tal vez cargar la misma imagen de JAR muchas veces hace que se creen muchos objetos de imagen separados (con contenido idéntico) en lugar de reutilizar una instancia por imagen individual? Esta es mi primera suposición.

+0

Cada imagen que uso más de una vez (y e es un número justo de ellos) se carga solo una vez como un objeto de Imagen. Varios objetos de botón y etiqueta en toda la aplicación se crean utilizando el mismo objeto de imagen, pero eso es algo que no puedo evitar. Desde que publiqué la pregunta logré encontrar una forma de optimizarla, aparentemente HttpConnection también consume bastante memoria. Mover un poco toda la comunicación HTTP a un único hilo separado y poner en orden el código para asegurarse de que muera y de que se recoja basura tan pronto como haya terminado. –

1

Hay algunas cosas que podría estar sucediendo aquí:

  • Es posible que haya visto la memoria utilizada antes de la recolección de basura, que no corresponde a la memoria real utilizada por la aplicación.
  • Algunos códigos de terceros que está ejecutando pueden estar agrupando algunas estructuras de datos internas para minimizar la asignación. Si bien la puesta en común es una estrategia viable, a veces parece una fuga. En ese caso, fíjate si hay API para 'cerrar' o 'eliminar' los objetos que no necesitas.
  • Finalmente, es posible que realmente tenga una fuga. En este caso, necesita obtener más detalles sobre lo que está sucediendo en la máquina virtual del emulador (aunque tenga en cuenta que no es necesariamente lo mismo que la máquina virtual del teléfono).

Asegúrate de que tu emulador use JRE 1.6 como JVM de respaldo. Si necesita utilizar las bibliotecas de tiempo de ejecución de erlyer JDK, use -Xbootclasspath:<path-to-rt.jar>.

Entonces, después de su aplicación se pone en el estado que desea ver, hacer %JAVA_HOME%\bin\jmap -dump:format=b,file=heap.bin <pid> (si no conoce el ID de su proceso, el uso jps)

Ahora usted tiene un volcado de la JVM montón. Puede analizarlo con jhat (viene con el JDK, un poco difícil de usar) o con perfiladores de terceros (mi preferencia es YourKit - es comercial, pero tienen licencias de evaluación de tiempo limitado)

+0

Analizar el volcado del montón es definitivamente el camino para encontrar fugas y el uso ineficiente de la memoria. Eclipse tiene una incorporada. Ventana> Perspectiva abierta> Analisis de memoria. luego abre el archivo de volcado. – tom

1

Tuve un problema similar con LWUIT en Java DTV. ¿Intentó enjuagar las imágenes cuando ya no las necesita (getAWTImage(). Flush())?

2

Los dispositivos móviles suelen tener muy poca memoria. Entonces debes usar algunos trucos para conservar y usar la memoria.

Tuvimos el mismo problema en un proyecto nuestro y lo resolvimos así.

para imágenes descargadas: Haga un caché donde coloque las imágenes. Si necesita una imagen, verifique si está en el mapa de caché, si no la descarga y la coloca allí, si es así, úsela. si la memoria está llena, elimine la imagen más antigua en el mapa de caché e inténtelo de nuevo.

para otras imágenes de recursos: guárdelas en la memoria solo durante el tiempo que pueda verlas, si no puede verlas, rompa la referencia y el gc hará la limpieza por usted.

Espero que esto ayude.

1

Uso EncodedImage y archivos de recursos cuando sea posible (archivos de recursos utilizan EncodedImage por defecto. Leer el Javadoc para tal. Otros comentarios también son correctos que hay que observar realmente la cantidad de memoria, incluso de alta RAM/dispositivos iOS Android se queda sin de la memoria bastante rápido con varias imágenes

evite escalar que elimina eficazmente el EncodedImage

no
Cuestiones relacionadas