问题描述:

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)

网友答案:

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
相关阅读:
Top