Search code examples
javaimagecachingimage-caching

Images getting cached and eating up my Heap Space


This question is a result of the answers provided to me for my previous question.

I was asked to use Eclipse MAT to investigate what is eating up my heap. Below are my observations (Top Consumers):

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

I have already fixed the issue with CacheManageServiceImpl, but require help with SunToolkit.

Below is the code that creates an Image object (which internally uses SunToolkit.imgCache)

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

Plz note that the Image object is only being created to get the width / height of the image which is required later in some logic.

Is there a way to disable SunToolkit image caching? Better yet, is there a way to clear this cache? Or is there a better way I can retrieve this information?

BTW for your reference, I am using the below command to run jboss (plz note the heap size arguments):

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


Solution

  • The image cache seems to be implemented by a class named SoftCache, its documentation states the following:

    A memory-sensitive implementation of the Map interface.

    A SoftCache object uses java.lang.ref.SoftReference to implement a memory-sensitive hash map. If the garbage collector determines at a certain point in time that a value object in a SoftCache entry is no longer strongly reachable, then it may remove that entry in order to release the memory occupied by the value object. All SoftCache objects are guaranteed to be completely cleared before the virtual machine will throw an OutOfMemoryError.

    So I would not worry about the memory taken by this cache since it will get cleared automatically when the memory is needed elsewhere.

    Edit: After reading the comments by SyntaxT3rr0r, I think it could still be worthwhile to call flush on the Image. If this is part of a larget method you could also set image to null or refactor so it goes out of scope sooner.

    Another possibility would be to try the ImageIO Api to retrieve the width and height. This should be possible by getting a ImageReader for the image type.