1

In Java, I have encountered an OutOfMemoryError due to the use of a BufferedImage. When I printed to the console how much memory was being used by that BufferedImage alone (in bytes), I noticed that he number of bytes being used increased exponentially. My results were as such:

    7396
    12996
    23104
    40804
    71824
    125316
    217156
    372100
    630436
    1060900
    1763584
    2903616
    4726276
    7595536
    12054784
    18887716
    29181604
    44435556
    66650896
    98446084
    143089444
    204547204
    -249500608
    -140383168

I used the following code to produce my result:

    while (true) {
        BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        DataBuffer buff = img.getRaster().getDataBuffer();
        System.out.println(buff.getSize() * DataBuffer.getDataTypeSize(buff.getDataType()) / 8); 
    }

Why is this increase so great and how can I keep this increase from happening? Also, what does it mean when there is a negative sign in front of the number (the last 2)?

EDIT:

Note that width and height change constantly, but I wouldn't expect them to increase (Sorry)

tobahhh
  • 369
  • 1
  • 3
  • 10
  • 2
    Please post an [mcve]. Your code snippet is not sufficient, at minimun the loop if missing, but probably more. – Polygnome Aug 28 '16 at 20:33
  • 1
    i think OP is wondering why the calculated size is getting changed (increasing) although the object creation parameters are constant (width, height, `TYPE_INT_ARGB` ) so theoretically the output should be always the same value. – Yazan Aug 29 '16 at 11:54
  • 1
    I think the 2 negative number means, those are integer and you have over the integer size.. Maybe it is https://en.wikipedia.org/wiki/Integer_overflow – Andrea De Gaetano Aug 29 '16 at 11:55
  • 2
    sure that this is the code that produces the increasing output? If I try this loop, the output stays the same. – P.J.Meisch Aug 29 '16 at 13:51
  • 1
    Your results are consistent with an ever increasing value of `width` and `height` (using the square root, I calculated the values to be 43, 57, 76, 101, 134, 177... etc). So, you are not showing the code you actually run. Using the code you posted, I can confirm @P.J.Meisch's findings, the output is constant. – Harald K Aug 30 '16 at 08:34

1 Answers1

1

When you create a BufferedImage of TYPE_INT_ARGB (or any TYPE_INT_*, really), you are creating an int backing array to hold your pixels, that is exactly width * height long. As a Java int is 32 bits, or 4 bytes, this array will use width * height * 4 bytes. The DataBuffer in your code is just a thin wrapper around this backing array.

So, the increase you see, is completely expected. Depending on the size of your heap, you will run out of memory at some point, trying to create ever larger BufferedImages.

The reason for the sudden negative values, are simply that your expression:

buff.getSize() * DataBuffer.getDataTypeSize(buff.getDataType()) / 8

will result in an integer overflow when buff.getSize() gets large enough.

As the * and / operators have equal precedence in the Java language, the expression will be evaluated from left to right, and the multiplication will overflow, even if the end result (after division by 8) should be a valid int. You can probably fix it by adding a parenthesis to force the division to happen first:

buff.getSize() * (DataBuffer.getDataTypeSize(buff.getDataType()) / 8)

Or simply use longs:

(long) buff.getSize() * (long) DataBuffer.getDataTypeSize(buff.getDataType()) / 8L
Community
  • 1
  • 1
Harald K
  • 26,314
  • 7
  • 65
  • 111