使用ImageIO.read(file)读取图像会导致Java堆空间不足的错误:java.lang.OutOfMemoryError。

6

我正在使用ImageIO API来写一个PNG文件。这段代码在一个循环中被调用,导致了OutOfMemory错误。是否有任何方法可以修复以下代码以避免OutOfMemory错误?或者唯一的选择是增加JVM堆大小?

File file = new File(resultMap.get("outputFile").toString());

//ImageIO to convert jpg to png
BufferedImage img = ImageIO.read(file);
file = new File(resultMap.get("outputFile").toString() + ".png");
ImageIO.write(img, "png", file);   

Java堆大小为1024M。


你的服务器当前的内存设置是什么,你正在处理的图像的大小/数量是多少? - Manish
你的堆设置有多大(-Xmx)?你读取的图片有多大?BufferedImage是一种完全未压缩的图像,因此即使是一个小小的2MB图像,在完全解压缩后也可能占用45MB的内存。如果在循环中进行这样的操作,我可以轻易地看出你如何耗尽内存。 - chubbsondubs
@chubbard 图像的大小为1MB或更小。除了BufferedImage,还有哪些替代方案? - arjunurs
你的输入文件是什么格式?如果它们本身就是PNG文件,那么你正在做很多不必要的工作。(如果这似乎很明显,我很抱歉,但我见过这种错误很多次)。 - Joachim Sauer
2个回答

9

我曾遇到一个类似的问题,需要读入36张图片,剪裁并逐一保存到新文件中。我发现在每次迭代后将图片设置为null可以让Java进行垃圾回收。如下所示:

BufferedImage img;
for (int i=0; i<36; i++) {
    img = ImageIo.ImageIO.read(anImageFile);
    /* Do what's needed with the image (cropping, resizing etc.) */
    ImageIO.write(img, "jpg", outputFile);
    img.flush();
    img = null;
}

我知道这是一篇旧帖,但我希望它能在未来帮到某个人。

4

为什么不尝试在BufferedImage上调用flush()。它会释放一些被占用的资源。


setUseCache不是用来启用/禁用磁盘缓存的吗?这怎么能防止OutOfMemoryError呢? - arjunurs
@apurv 抱歉,我一直以为 API 是缓存的。我修改了答案,请您再试一下。 - Ramesh PVK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接