为什么 BufferedImages 在程序运行时会增加它们使用的 ram 数量?
Why do BufferedImages increase the amount of ram they use as the program runs?
在Java中,由于使用了BufferedImage,我遇到了OutOfMemoryError。当我向控制台打印出 BufferedImage 单独使用了多少内存(以字节为单位)时,我注意到他使用的字节数呈指数增长。我的结果是这样的:
7396
12996
23104
40804
71824
125316
217156
372100
630436
1060900
1763584
2903616
4726276
7595536
12054784
18887716
29181604
44435556
66650896
98446084
143089444
204547204
-249500608
-140383168
我使用以下代码生成结果:
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);
}
为什么这种增加如此之大,我怎样才能避免这种增加的发生?另外,数字前面有一个负号(最后2个)是什么意思?
编辑:
请注意宽度和高度不断变化,但我不希望它们增加(抱歉)
当您创建 TYPE_INT_ARGB
的 BufferedImage
(或任何 TYPE_INT_*
,实际上)时,您正在创建一个 int
支持数组来保存您的像素,即恰好 width * height
长。由于 Java int
是 32 位或 4 字节,因此该数组将使用 width * height * 4
字节。您代码中的 DataBuffer
只是这个后备数组的薄包装。
因此,您看到的增长完全在意料之中。根据堆的大小,您会 运行 在某个时候内存不足,试图创建更大的 BufferedImage
s。
突然出现负值的原因,很简单,就是你的表达:
buff.getSize() * DataBuffer.getDataTypeSize(buff.getDataType()) / 8
当 buff.getSize()
足够大时, 将导致 integer overflow。
作为Java语言中的*
和/
运算符have equal precedence,表达式会从左到右求值,乘法会溢出,即使如果最终结果(除以 8)应该是有效的 int
。您可以通过添加括号强制先进行除法来修复它:
buff.getSize() * (DataBuffer.getDataTypeSize(buff.getDataType()) / 8)
或者简单地使用 long
s:
(long) buff.getSize() * (long) DataBuffer.getDataTypeSize(buff.getDataType()) / 8L
在Java中,由于使用了BufferedImage,我遇到了OutOfMemoryError。当我向控制台打印出 BufferedImage 单独使用了多少内存(以字节为单位)时,我注意到他使用的字节数呈指数增长。我的结果是这样的:
7396
12996
23104
40804
71824
125316
217156
372100
630436
1060900
1763584
2903616
4726276
7595536
12054784
18887716
29181604
44435556
66650896
98446084
143089444
204547204
-249500608
-140383168
我使用以下代码生成结果:
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);
}
为什么这种增加如此之大,我怎样才能避免这种增加的发生?另外,数字前面有一个负号(最后2个)是什么意思?
编辑:
请注意宽度和高度不断变化,但我不希望它们增加(抱歉)
当您创建 TYPE_INT_ARGB
的 BufferedImage
(或任何 TYPE_INT_*
,实际上)时,您正在创建一个 int
支持数组来保存您的像素,即恰好 width * height
长。由于 Java int
是 32 位或 4 字节,因此该数组将使用 width * height * 4
字节。您代码中的 DataBuffer
只是这个后备数组的薄包装。
因此,您看到的增长完全在意料之中。根据堆的大小,您会 运行 在某个时候内存不足,试图创建更大的 BufferedImage
s。
突然出现负值的原因,很简单,就是你的表达:
buff.getSize() * DataBuffer.getDataTypeSize(buff.getDataType()) / 8
当 buff.getSize()
足够大时,将导致 integer overflow。
作为Java语言中的*
和/
运算符have equal precedence,表达式会从左到右求值,乘法会溢出,即使如果最终结果(除以 8)应该是有效的 int
。您可以通过添加括号强制先进行除法来修复它:
buff.getSize() * (DataBuffer.getDataTypeSize(buff.getDataType()) / 8)
或者简单地使用 long
s:
(long) buff.getSize() * (long) DataBuffer.getDataTypeSize(buff.getDataType()) / 8L