我正在开发一个Java软件,它不断获取桌面的截图,将其存储在BufferedImage对象中,然后将其写入jpg文件。在某些时候,该程序会导致java.lang.OutOfMemoryError:Java堆空间异常。由于我拍摄截图并将其保存为文件,因此我不再需要内存中的先前BufferedImage对象,因此我可以将它们丢弃。 Java似乎没有识别这些对象,因此它们可能仍在内存中。有没有办法在JVM的内存中删除它们,所以它不会用完?连续调用System.gc()可能无济于事。有什么想法吗?
以下是供参考的代码:
public BufferedImage getScreenShot() {
BufferedImage screenImage = null;
try {
GraphicsEnvironment ge= GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice[] screens=ge.getScreenDevices();
Rectangle allScreenBounds=new Rectangle();
for(GraphicsDevice screen: screens)
{
Rectangle screenbounds = screen.getDefaultConfiguration().getBounds();
allScreenBounds.width+=screenbounds.width;
allScreenBounds.height=Math.max(allScreenBounds.height, screenbounds.height);
}
Robot robot = new Robot();
screenImage = robot.createScreenCapture(allScreenBounds);
} catch (Exception ex) {
Logger.getLogger(Screen.class.getName()).log(Level.SEVERE, null, ex);
}
return screenImage;
}
然后我只有一个循环,它不断调用该方法来生成BufferedImage对象,调整它的大小,并将其写入这样的文件:
while(true){
FileImageOutputStream out = new FileImageOutputStream(f);
writer.setOutput(out);
IIOImage image = new IIOImage(ImageUtils.resize(getScreenShot(), width, height),null, null);
writer.write(null, image, iwp);
writer.dispose();
}
答案 0 :(得分:5)
您只需要删除先前使用的BufferedImage对象的引用变量。然后垃圾收集器会在需要时自动释放它们占用的内存。
由于你不断拍摄屏幕截图,所以我认为你会有某种循环的东西,你只会创建新的变量,但早期使用的变量也会出现在内存中,因为它们的引用仍然存在。 / p>
所以尝试删除他们的引用变量。然后,当内存几乎被填满时,Java 垃圾收集器将自动进入并为您释放内存。
答案 1 :(得分:1)
是的,当变量的使用完成后,告诉垃圾收集器不再使用它。您可以通过将对象引用为null来表示。
在你的案例之后
writer.write(null, image, iwp);
尝试添加此行
image=null;