0

I have very simple program which saves screenshots to ArrayList - for example I take 100 screenshots, add them to the list and then I clear the list. Like this:

public static void main(String[] args) {
    JFrame frame = new JFrame(); // creating simple JFrame
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    List<BufferedImage> list = new ArrayList<>();
    for (int i = 1; i <= 100; i++) {
        BufferedImage capture = makeScreenShot();
        list.add(capture);
        System.out.println("capture saved to arraylist " + i);
    }
    list.clear();
}

and the method makeScreenShot:

private static BufferedImage makeScreenShot() {
    Robot robot = null;
    try {
        robot = new Robot();
    } catch (AWTException e) {
        e.printStackTrace();
    }
    Toolkit toolkit = Toolkit.getDefaultToolkit();
    Rectangle screenBounds = new Rectangle(toolkit.getScreenSize());
    BufferedImage capture = robot.createScreenCapture(screenBounds);
    return capture;
}

If I run this simple program, my Task Manager (Windows) shows that this program uses about 1GB of RAM. Why the Java garbage colllector doesn't remove all the BufferedImages from RAM memory? There are no references to these BufferedImages, Am I right?

honzzyk
  • 169
  • 2
  • 7
  • Of course there are references stored in your `List list`. – wero Jul 23 '15 at 21:21
  • When? There are references to the images while you're capturing them; after you do `list.clear()`, then there aren't any. – user253751 Jul 23 '15 at 21:22
  • @immibis after finishing the list.clear() command, there is still 1 GB in RAM used. 10 minutes after this command. – honzzyk Jul 23 '15 at 21:26
  • what if you call `System.gc()` after `list.clear()`? I know its bad manner, but still – JohnnyAW Jul 23 '15 at 21:29
  • @JohnnyAW I have tried that - still the same behaviour. – honzzyk Jul 23 '15 at 21:34
  • @honzzyk ok, then try to repeat the `for-loop` right after `list.clear` and see, if your memory consumption will grow – JohnnyAW Jul 23 '15 at 21:36
  • @JohnnyAW the memory grows up to 1,5 GB after 4 for-loops. For a moment it stops growing but if the index in the loop is about 80, the memory grows again. – honzzyk Jul 23 '15 at 21:47
  • @wero there shouldn't be any references if I call list.clear(). – honzzyk Jul 23 '15 at 22:09
  • @durron597 It is not the same problem as you suggested - In that problem there are images saved to harddisk. I have them only in the memory. – honzzyk Jul 23 '15 at 22:12
  • @honzzyk There is no difference. The problem is caused for the same reason and the answers will answer your question. – durron597 Jul 23 '15 at 22:12
  • @durron597 ok - if I set Xmx32M as suggested in the other problem, after taking the 4th screenshot, my program throws OutOfMemoryError: Java heap space – honzzyk Jul 23 '15 at 22:18
  • @honzzyk Thats because you take 100 screenshots before clearing the memory. You need to have at least enough for the first 100 screenshots. – durron597 Jul 23 '15 at 22:20
  • @durron597 I know. But I need lots of memory for lots of screenshots. This is simple code, but imagine that I need for example 300 screenshots, With this screenshots I'll do some work and than I need to erase my RAM. – honzzyk Jul 23 '15 at 22:23
  • @honzzyk well then you need the memory usage and I'm not sure what your problem is? – durron597 Jul 23 '15 at 22:27
  • @durron597 my problem is that after I do the hypothetical work I need to erase my RAM. But this app consumes 1 GB of RAM after finishing its job (there is only simple JFrame visible) – honzzyk Jul 23 '15 at 22:33

1 Answers1

1

I agree with durron597, this question does have an answer already. And, as he also said, you can't give the program less memory than it needs to complete a cycle of screen capturing, processing and list clearing.

As stated in the accepted answer, the JVM will use as much memory as it can, and that's OK.

Your program will stabilize its memory usage at some point and most likely run forever. I did try that, actually (not forever though).

But I liked the lower heap size version of the test - this is how I set it up:

JVM

This is how much memory it used after that:

Memory Usage

And it's running for 6 hours (almost 700k screenshots taken!):

Running Time

So, if you really need to, you can still limit its memory usage - but do you have to?

From the javadocs: "Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse."

So, System.gc() is just a suggestion - and might be a really bad one.

Community
  • 1
  • 1
Daniel
  • 387
  • 1
  • 7
  • 17