为什么 BufferedImage 需要超出其数据数组大小的大量内存?
我正在尝试确定给定的 TYPE_INT_ARGB BufferedImage
将使用这样的方式,对于正在进行图像处理的程序,我可以根据我们提供的图像大小设置合理的最大堆。
我编写了以下程序作为测试,然后用它来确定在没有 OutOfMemoryError
的情况下运行该程序的最小最大堆:(
import java.awt.image.BufferedImage;
public class Test {
public static void main(String[] args) {
final int w = Integer.parseInt(args[0]);
final int h = Integer.parseInt(args[1]);
final BufferedImage img =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
System.out.println((4*w*h) >> 20);
}
}
打印的值是 int[ 的预期大小) ]
其中存储了 BufferedImage
的像素数据。)我期望找到的是所需的最大堆类似于 x + c
,其中x
是数据数组的大小,c
是一个常量,由加载的类的大小、BufferedImage
对象等组成这是我发现的(所有值均以 MB 为单位):
4*w*h min max heap ----- ------------ 5 - 10 15 20 31 40 61 80 121 160 241
1.5x
非常适合观察结果。 (请注意,我发现 5MB 图像没有最小值。)我不明白我所看到的。这些额外的字节是什么?
I'm trying to determine how much heap any given TYPE_INT_ARGB BufferedImage
will use so that, for a program which is doing some image processing, I can set a reasonable max heap based on the size of image we feed it.
I wrote the following program as a test, which I then used to determine the least maximum heap under which it would run without an OutOfMemoryError
:
import java.awt.image.BufferedImage;
public class Test {
public static void main(String[] args) {
final int w = Integer.parseInt(args[0]);
final int h = Integer.parseInt(args[1]);
final BufferedImage img =
new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
System.out.println((4*w*h) >> 20);
}
}
(The printed value is the expected size of the int[]
in which the BufferedImage
's pixel data is stored.) What I expected to find was that the required max heap is something like x + c
, where x
is the size of the data array and c
is a constant consisting of the sizes of the classes which are loaded, the BufferedImage
object, etc. This is what I found instead (all values are in MB):
4*w*h min max heap ----- ------------ 5 - 10 15 20 31 40 61 80 121 160 241
1.5x
is a good fit for the observations. (Note that I found no minimum for the 5MB image.) I don't understand what I'm seeing. What are these extra bytes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Oracle 的 VM 中似乎在 1.6.0_16 和 1.6.0_20 之间引入了一个错误。您甚至可以将问题简化为分配 int 数组,因为问题不仅与 BufferedImage 有关。
在 1.6.0_16 中,我至少需要 413 MB 堆来分配一个包含 100,000,000 个元素的 int 数组,这看起来很合理。在 1.6.0_20 中,相同的操作至少需要 573 MB 堆空间,尽管在分配数组后实际只使用了大约 400,000,000 字节。
There seem to be a bug in Oracle's VM introduced somewhere between 1.6.0_16 and 1.6.0_20. You can even reduce the problem to allocating an int array, as the problem is not only related to BufferedImage.
With 1.6.0_16, I need at least 413 MB heap to allocate an int array with 100,000,000 elements, which seem reasonable. With 1.6.0_20, the same operation requires at least 573 MB heap space, although only appr 400,000,000 bytes are actually used after allocating the array.
经过进一步调查,问题似乎是堆中的老一代无法充分扩展以容纳图像的数据数组,尽管堆中总体上有足够的可用内存。
有关如何扩展老一代的更多详细信息,请参阅
On further investigation, the problem appears to be that the Old Generation in the heap is not able to expand sufficiently to accommodate the image's data array, despite that there is enough free memory in the heap at large.
For further details about how to expand the Old Generation, see this question.
问题在于 BufferedImage 对象以未压缩的格式将图像存储在内存中。对此有一个有效的解决方案:您可以将映像存储在硬盘上,而不必担心堆大小或物理内存限制。它最多可以存储 2,147,483,647 像素(或 46,340 x 46,340 像素)。 BigBufferedImage 解决了这个问题。
创建一个空的BigBufferedImage:
加载一个已有的图像到BigBufferedImage:
渲染图像的一部分:
BigBufferedImage的实现:
The problem is that the BufferedImage object stores the image in the memory in uncompresed format. There is an effective solution for this: you can store the image on the hard drive and you don't have to worry about the heap size or the physical memory limit. It can store maximum 2,147,483,647 pixels (or 46,340 x 46,340 pixels). BigBufferedImage solves this problem.
Create az empty a BigBufferedImage:
Load an existent image to BigBufferedImage:
Render the part of the image:
The implementation of BigBufferedImage: