Управление использованием памяти при получении множества скриншотов в Java - PullRequest
2 голосов
/ 27 января 2012

Я занимаюсь разработкой программного обеспечения на 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 ]

5 голосов
/ 27 января 2012

Вам просто нужно удалить ссылочные переменные ранее использованных объектов BufferedImage. Тогда сборщик мусора автоматически освободит занятую ими память при необходимости.

Поскольку вы постоянно делаете снимки экрана, я думаю, что у вас будут какие-то циклы, и вы будете создавать только новые переменные, но ранее использовавшиеся переменные также будут присутствовать в памяти, так как их ссылка все еще существует.

Так что попробуйте удалить их ссылочные переменные. Затем, когда память будет почти заполнена, Java Сборщик мусора автоматически вступит в игру и освободит вашу память для вас.

1 голос
/ 27 января 2012

Да, когда использование переменной завершено, скажите сборщику мусора, что она больше не используется.Вы можете сказать это, сославшись на объект null.

В вашем случае после этой строки

writer.write(null, image, iwp); 

попробуйте добавить эту строку

image=null;
...