【发布时间】:2014-11-19 09:24:07
【问题描述】:
我需要读取许多图像才能一个接一个地处理它们。一开始我使用IO库读取每张图片:
File outputfile = new File(uri);
BufferedImage imgBuff = ImageIO.read(outputfile);
imgBuff.flush();
imgBuff = null;
outputfile = null;
但是它占用了大量内存并且我的进程崩溃了。在做了一些研究之后,我发现使用 java IO 库读取许多图像存在很多问题。我使用这个简单的程序来验证内存泄漏是由使用此图像http://tinyurl.com/ku3ff7w 读取图像引起的:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.junit.Test;
public class MemoryLeakTest {
static File outputfile = null;
static BufferedImage imgBuff = null;
public static void main(String args[]) {
String uri = "/home/user/Pictures/image.jpg";
outputfile = new File(uri);
for (int i = 0; i < 15000; i++) {
outputfile = new File(uri);
try {
imgBuff = ImageIO.read(outputfile);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (imgBuff != null) {
imgBuff.flush();
imgBuff = null;
}
outputfile = null;
}
}
}
}
我也尝试过使用 ImageJ 库,但是将图像转换为 BufferedImage 时出现了同样的问题:
ImagePlus bb = op.openImage(uri);
imgBuff = bb.getBufferedImage();
bb.killStack();
bb.flush();
bb.close();
我想我可以将图像读取为字节数组,这样可以解决问题,但解决方案并不理想。有谁知道是否有任何库或方法可以在 Java 中读取许多图像而不会耗尽内存?
【问题讨论】:
-
我修改了您的示例以避免代码重复,引入了
finally块(我认为这更好,但在这种情况下并不真正相关)。运行它没有任何问题。据我所知,没有内存泄漏。我什至试图通过使用-Xmx16m命令行选项来强制它。也许您需要特定的 Java 版本、参数或特殊的 JPEG 来重现问题? -
感谢您的回复。这是我正在使用的图像tinyurl.com/ku3ff7w。也许是因为那张图片要大得多。
-
@Victoria - 我只是用 2mb 的图像运行代码没有问题 - 但是我已经将我的最大堆空间增加到 1GB,并且通过插入一些对
Runtime.getRuntime().freeMemory()的调用,我可以看到程序使用相当大的一部分(〜50%)。你有没有分析过自己的内存使用情况?尝试增加你的堆大小 (-Xmx),也许每隔几次迭代就调用一次System.gc(),看看是否有帮助。 -
即使使用大图像,我也可以使用
-Xmx16m运行示例。那里没有内存泄漏。我认为您要么使用了可能存在错误的特殊 Java 版本,要么只是混淆了“内存泄漏”和“高内存使用”这两个术语。分析是一个好主意,可以找出内存卡在哪里。在代码中插入System.gc()通常是个坏主意,因为Java 会在某个时候释放垃圾收集器可收集的任何内存。如果发生内存泄漏,内存将无法回收。
标签: java image memory-leaks