图像被缓存并吃掉了我的堆空间

时间:2011-03-09 12:35:50

标签: java image caching image-caching

这个问题是我为previous question提供的答案的结果。

我被要求使用Eclipse MAT来调查吃掉堆的东西。以下是我的观察(热门消费者):

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

我已使用CacheManageServiceImpl解决了该问题,但需要SunToolkit的帮助。

下面是创建Image对象的代码(内部使用SunToolkit.imgCache

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

Plz请注意,Image对象仅用于获取图像的宽度/高度,稍后需要在某些逻辑中使用。

有没有办法禁用SunToolkit图片缓存?更好的是,有没有办法清除这个缓存?或者有更好的方法可以检索这些信息吗?

BTW供您参考,我使用下面的命令来运行jboss(请注意堆大小参数):

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

萨米特

2 个答案:

答案 0 :(得分:3)

图像缓存似乎是由名为SoftCache的类实现的,其文档说明如下:

  

Map接口的内存敏感实现。

     

SoftCache个对象使用java.lang.ref.SoftReference   实现对内存敏感的哈希映射。如果是垃圾   collector在某个时间点确定一个值对象   SoftCache条目不再可以强烈访问,然后可以   删除该条目以释放值占用的内存   宾语。所有SoftCache个对象都保证完全   在虚拟机抛出之前清除   OutOfMemoryError

所以我不担心这个缓存占用的内存,因为当其他地方需要内存时它会被自动清除。

修改:在SyntaxT3rr0r阅读评论后,我认为在图片上调用flush仍然值得。如果这是一个larget方法的一部分,你也可以将image设置为null或重构,以便它更快地超出范围。

另一种可能性是尝试使用ImageIO Api检索宽度和高度。这应该是通过获得ImageReader for the image type来实现的。

答案 1 :(得分:1)

您的Image对象是否可能长时间保持在范围内?例如,如果它包含在长时间运行的代码块的外部范围内,则可能无法正确地进行垃圾回收。

有时(在极少数情况下),将Image对象引用显式设置为null是有益的。在我上面提到的情况下也是如此。有关详细信息,请参阅以下问题:Does assigning objects to null in Java impact garbage collection?