简体   繁体   English

Java BufferedImage 内存消耗

[英]Java BufferedImage memory consumption

Our application generates images.我们的应用程序生成图像。 The memory consumed by BufferedImage generates an out of memory exception: BufferedImage消耗的内存产生内存不足异常:

java.lang.OutOfMemoryError: Java heap space java.lang.OutOfMemoryError:Java 堆空间

This happens with the following line:这发生在以下行:

BufferedImage result = new BufferedImage(2540, 2028, BufferedImage.TYPE_INT_ARGB);

When checking free memory just before this instruction it shows that I have 108MB free memory.在这条指令之前检查空闲内存时,它显示我有 108MB 空闲内存。 The approach I use to check memory is:我用来检查内存的方法是:

Runtime rt = Runtime.getRuntime();
rt.gc();
long maxMemory = rt.maxMemory();
long usedMemory = rt.totalMemory() - rt.freeMemory();
long freeMem = maxMemory - usedMemory;

We don't understand how the BufferedImage can consume more than 100MB of memory.我们不明白BufferedImage怎么会消耗超过 100MB 的内存。 It should use 2540 * 2028 * 4 bytes, which is ~20 MB.它应该使用 2540 * 2028 * 4 字节,即 ~20 MB。

Why is so much memory consumed when creating the BufferedImage ?为什么在创建BufferedImage时消耗了这么多内存? What we can do to reduce this?我们可以做些什么来减少这种情况?

Asking Runtime for the amount of free memory is not really reliable in a multithreaded environment, as the memory could be used up by another thread right after you measured.在多线程环境中向 Runtime 询问可用内存量并不是真正可靠的,因为在您测量之后内存可能会被另一个线程用完。 Also, you are using maxMemory - usedMemory , which is not the amount of free memory, but rather what the VM thinks it can make available at most - it may be that the host system can not satisfy a request for more memory, while the VM still believes it can enlarge the heap.此外,您使用的是maxMemory - usedMemory ,这不是可用内存量,而是 VM认为它最多可以提供的内存量 - 可能是主机系统无法满足对更多内存的请求,而 VM仍然相信它可以扩大堆。

It's also fully possible that your VM has 108 MB free , but no 20MB in one chunk is available.也完全有可能您的 VM有 108 MB 可用空间,但一个块中没有 20MB 可用。 The type of BufferedImage you are trying to create is ultimately backed by an int[] array, which must be allocated as a contiguous memory block.您尝试创建的 BufferedImage 类型最终由 int[] 数组支持,该数组必须作为连续内存块分配。 That means if no contiguous 20MB block is available on the heap, no matter how much total free memory there is otherwise, you will get an OutOfMemoryError.这意味着如果堆上没有可用的连续 20MB 块,无论有多少可用内存,您都会收到 OutOfMemoryError。 The situation is further complicated by the garbage collector used - each GC has different strategies for memory allocation;使用的垃圾收集器使情况更加复杂——每个 GC 都有不同的内存分配策略; a sizable portion of the heap may be set aside for thread local memory allocation.可以留出相当大的堆部分用于线程本地内存分配。

Without any information how large the heap is in total, which GC you are using (and which VM for the matter), there are too many variables to point a finger on a culprit.如果没有任何关于堆总共有多大的信息,你正在使用哪个 GC(以及哪个 VM),有太多的变量无法指出罪魁祸首。


Edit: Find out which GC is used ( Java 7 (JDK 7) garbage collection and documentation on G1 ) and have a glance on its specific pros and cons - especially what capabilities it offers in terms of heap compaction and how large its generations are by default.编辑:找出使用的 GC( Java 7 (JDK 7) 垃圾收集和 G1 上的文档),并了解其特定的优缺点 - 特别是它在堆压缩方面提供的功能以及它的代有多大默认。 That would be the parameters to play with.那将是要使用的参数。 Running the application with GC messages on may also provide insight on whats going on.在 GC 消息开启的情况下运行应用程序也可以提供对正在发生的事情的洞察。

Considering your heap is only 900MB in size, 100MB free means your pretty close to the limit already - my first go to cure would be to simply assign the VM a much larger heap, lets say 2GB.考虑到您的堆只有 900MB 的大小,100MB 空闲意味着您已经非常接近限制了 -我的第一个解决方法是简单地为 VM 分配一个更大的堆,比如说 2GB。 If you need to conserve memory your only bet is tuning the GC parameters (possibly select another GC) - and to be honest I have no experience with that.如果您需要节省内存,您唯一的选择就是调整 GC 参数(可能选择另一个 GC)——老实说,我没有这方面的经验。 There are plenty of articles on the topic of GC tuning available, though.不过,有很多关于 GC 调优主题的文章可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM