繁体   English   中英

Java BufferedImage 内存消耗

[英]Java BufferedImage memory consumption

我们的应用程序生成图像。 BufferedImage消耗的内存产生内存不足异常:

java.lang.OutOfMemoryError:Java 堆空间

这发生在以下行:

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

在这条指令之前检查空闲内存时,它显示我有 108MB 空闲内存。 我用来检查内存的方法是:

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

我们不明白BufferedImage怎么会消耗超过 100MB 的内存。 它应该使用 2540 * 2028 * 4 字节,即 ~20 MB。

为什么在创建BufferedImage时消耗了这么多内存? 我们可以做些什么来减少这种情况?

在多线程环境中向 Runtime 询问可用内存量并不是真正可靠的,因为在您测量之后内存可能会被另一个线程用完。 此外,您使用的是maxMemory - usedMemory ,这不是可用内存量,而是 VM认为它最多可以提供的内存量 - 可能是主机系统无法满足对更多内存的请求,而 VM仍然相信它可以扩大堆。

也完全有可能您的 VM有 108 MB 可用空间,但一个块中没有 20MB 可用。 您尝试创建的 BufferedImage 类型最终由 int[] 数组支持,该数组必须作为连续内存块分配。 这意味着如果堆上没有可用的连续 20MB 块,无论有多少可用内存,您都会收到 OutOfMemoryError。 使用的垃圾收集器使情况更加复杂——每个 GC 都有不同的内存分配策略; 可以留出相当大的堆部分用于线程本地内存分配。

如果没有任何关于堆总共有多大的信息,你正在使用哪个 GC(以及哪个 VM),有太多的变量无法指出罪魁祸首。


编辑:找出使用的 GC( Java 7 (JDK 7) 垃圾收集和 G1 上的文档),并了解其特定的优缺点 - 特别是它在堆压缩方面提供的功能以及它的代有多大默认。 那将是要使用的参数。 在 GC 消息开启的情况下运行应用程序也可以提供对正在发生的事情的洞察。

考虑到您的堆只有 900MB 的大小,100MB 空闲意味着您已经非常接近限制了 -我的第一个解决方法是简单地为 VM 分配一个更大的堆,比如说 2GB。 如果您需要节省内存,您唯一的选择就是调整 GC 参数(可能选择另一个 GC)——老实说,我没有这方面的经验。 不过,有很多关于 GC 调优主题的文章可用。

暂无
暂无

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

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