在Java中获取许多屏幕截图时管理内存使用情况

时间:2012-01-27 06:05:04

标签: java memory screenshot bufferedimage out-of-memory

我正在开发一个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();
}

2 个答案:

答案 0 :(得分:5)

您只需要删除先前使用的BufferedImage对象的引用变量。然后垃圾收集器会在需要时自动释放它们占用的内存。

由于你不断拍摄屏幕截图,所以我认为你会有某种循环的东西,你只会创建新的变量,但早期使用的变量也会出现在内存中,因为它们的引用仍然存在。 / p>

所以尝试删除他们的引用变量。然后,当内存几乎被填满时,Java 垃圾收集器将自动进入并为您释放内存。

答案 1 :(得分:1)

是的,当变量的使用完成后,告诉垃圾收集器不再使用它。您可以通过将对象引用为null来表示。

在你的案例之后

writer.write(null, image, iwp); 

尝试添加此行

image=null;