2011-03-09 17 views
5

Esta pregunta es el resultado de las respuestas que se me proporcionaron para mi previous question.Imágenes que se almacenan en la memoria caché y se comen mi Heap Space

Me pidieron que use Eclipse MAT para investigar lo que está consumiendo mi montón. A continuación son mis observaciones (Top Consumidores):

class sun.awt.SunToolkit         333.7 MB 
com.tennisearth.service.impl.CacheManagerServiceImpl  136 MB 
org.apache.jasper.servlet.JspServlet      91.5 MB 

ya he solucionado el problema con CacheManageServiceImpl, pero requieren ayuda con SunToolkit.

A continuación se muestra el código que crea un objeto de imagen (que utiliza internamente SunToolkit.imgCache)

Image img = new ImageIcon(imagePath).getImage(); 
int imageWidth = img.getWidth(null); 
int imageHeight = img.getHeight(null); 

nota del PLZ que el objeto de imagen única se está creando para obtener el ancho/altura de la imagen que se requiere más adelante en algo de lógica.

¿Hay alguna manera de deshabilitar el almacenamiento en memoria caché de imágenes SunToolkit? Mejor aún, ¿hay alguna manera de borrar este caché? ¿O hay una mejor manera de recuperar esta información?

cierto para su referencia, estoy usando el comando siguiente para ejecutar JBoss (nota del PLZ los argumentos Tamaño de pila):

java -Dprogram.name=run.sh -server -Xms256m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m -verbose:gc -Xloggc:/data1/logs/jboss/GC.log -XX:+HeapDumpOnOutOfMemoryError -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000 -Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=false -Djava.net.preferIPv4Stack=true -Djava.library.path=/usr/local/java/jboss-4.2.2.GA/bin/native -Djava.endorsed.dirs=/usr/local/java/jboss-4.2.2.GA/lib/endorsed -classpath /usr/local/java/jboss-4.2.2.GA/bin/run.jar:/usr/local/java/jdk1.6.0_06/lib/tools.jar org.jboss.Main -c default -b <IP_ADDRESS> -Djboss.messaging.ServerPeerID=1 

Sumit

+1

hay un montón * de problemas en Java relacionados con las imágenes y el almacenamiento en caché de imágenes. Me viene a la mente el infame * flush() * solución alternativa alrededor de los defectos de API. Anular imágenes no siempre es suficiente: a veces necesitas llamar a * flush() * y simplemente no tiene sentido. Si está en un servidor, obtendría esa información de ancho/alto al ejecutar externamente el comando * identify * de ImageMagick. Es un poco doloroso ejecutar un proceso externo, pero luego cargar una imagen solo para obtener su ancho/alto en un servidor también es bastante pesado. – SyntaxT3rr0r

+0

otra opción ... Estábamos procesando por lotes todas nuestras imágenes y colocando la información de ancho/alto directamente en el nombre de archivo de la imagen: * mypic.jpg * se convierte en * mypic640x480.jpg *. Luego simplemente extrajimos el (w, h) del nombre de archivo ... – SyntaxT3rr0r

+0

si desea buscar en Google sobre este tema, aquí hay una cita interesante: * Hemos visto el problema de la descarga en otras plataformas aparte de OS X, así que creo que " Sun debe implementar la corrección adecuada, implementando finalizar en ToolkitImage para forzar una descarga antes de que GC recupere la imagen. ¿Alguien ha informado esto a Sun? * – SyntaxT3rr0r

Respuesta

3

La imagen parece ser implementada por una clase llamada SoftCache, sus estados de documentación los siguientes:

Una implementación de la memoria sensible de la interfaz Map.

Un objeto SoftCache usa java.lang.ref.SoftReference para implementar un mapa hash sensible a la memoria. Si el recopilador de basura determina en un determinado momento que un objeto de valor en una entrada SoftCache ya no es muy accesible, puede eliminar esa entrada para liberar la memoria ocupada por el objeto de valor . Todos los objetos SoftCache están garantizados para ser completamente borrados antes de que la máquina virtual arroje un OutOfMemoryError.

Así que no me preocuparía la memoria tomada por este caché, ya que se borrará automáticamente cuando la memoria se necesite en otro lugar.

Editar: Después de leer los comentarios de SyntaxT3rr0r, creo que aún podría ser útil para llamar flush en la imagen. Si esto es parte de un método de gran tamaño, también podría establecer que la imagen sea nula o refactorizada para que salga del alcance antes.

Otra posibilidad sería probar el ImageIO Api para recuperar el ancho y la altura. Esto debería ser posible obteniendo un ImageReader for the image type.

+1

Muchas gracias por su aclaración. Me alegro de no tener que preocuparme más por esto :) – Sumit

+0

Acabo de ver su edición, aún me gustaría utilizar el almacenamiento en caché de imágenes para acelerar el proceso de creación del objeto de imagen. Creo que el lavado de la imagen no podrá usar este caché. ¿Derecha? – Sumit

+1

@Sumit, no sé exactamente qué cachés son eliminados por esa llamada. Si consulta repetidamente el ancho y el alto para la misma ruta de imagen, también podría tener sentido implementar un caché simple, como un 'Map '. Eso evitaría la necesidad de recrear la imagen una vez que el gc aclare la imgCache. –

1

¿Es posible que el objeto de imagen permanece en su alcance por mucho tiempo ¿períodos de tiempo? Por ejemplo, si está contenido en el ámbito externo de un bloque de código que se ejecuta durante largos períodos de tiempo, es posible que no se recopile correctamente.

A veces (en casos excepcionales), es beneficioso establecer explícitamente su referencia de objeto de imagen a nulo. Esto sería cierto en el caso que mencioné anteriormente. Vea la siguiente pregunta para obtener más información: Does assigning objects to null in Java impact garbage collection? caché

Cuestiones relacionadas