【问题标题】:Java Images take up too much memoryJava图像占用太多内存
【发布时间】:2010-10-06 01:21:32
【问题描述】:

我有一个使用大量图像的程序。 它从文件中加载大量图像,并存储它们,因此它们只加载一次。 它还会创建多个 BufferedImage,大约 400x400,不会超过 10 个。

文件中的图像总大小约为 6MB。 每个 BufferedImage 应约为 400x400x4=640KB。

但是,内存使用量是 500MB!

其中一些将用于程序的其余部分,但我很确定图像占据了大部分空间。

有人知道该怎么办吗? 还是使用更少内存的 BufferedImage 的替代品?

【问题讨论】:

  • 听起来很可疑,在我责怪库之前,我会先责怪你的代码,抱歉。小心粘贴一些吗?当你强制垃圾收集器运行时会发生什么?必须有一些可用的 java 内存分析器。 google.com/…
  • 同意 Hamish,这可能是加载和缓存图像的代码中的错误。也许它实际上不止一次地加载和缓存图像。
  • 是的,最初我认为这是内存泄漏。但是一旦开始,最多只能制作 10 个 400x400 的 BufferedImage。一开始它是 500MB,从那里看起来并没有增长多少,一开始只是一个巨大的数量。 @Hamish我们尝试强制垃圾收集器,但这并没有做太多。当我有机会时,我会研究内存分析工具。至于粘贴代码,这将是相当不切实际的,因为它实际上是相当意大利面条式的。我们正在为大学的一个小组项目开发一款冒险游戏,代码完全是一团糟=s。
  • @DaniEL,你怎么知道是图片导致了这个问题?如果您不小心,您可以轻松创建千兆字节的数据。例如,如果您尝试解决 TSP 问题,内存和 CPU 使用率可能会呈指数级增长。您需要进行分析以找出实际的瓶颈。
  • 我刚刚玩过 jvisualvm,出于某种荒谬的原因,我实际上确实有 206 个 BufferedImages。但奇怪的是,对于它们中的大多数,我的对象都没有引用它们。在分析器中对它们的唯一引用是 biimage、referent、bImg、bufImg 和类似的东西。这些都不是我的代码的一部分。知道为什么他们仍然有参考吗?或者如何摆脱它们?

标签: java image memory bufferedimage


【解决方案1】:

在我看来,您的应用程序(而不是库)存在内存泄漏。在第一种情况下,您应该尝试使用标准 Java 内存分析器来识别泄漏。

编辑

现在您已经确定有很多 BufferedImages 在附近闲逛,接下来您需要做的是弄清楚为什么它们仍然可以访问。进行堆转储,查看一些实例,看看它们是如何连接到堆根的;见http://download.oracle.com/javase/6/docs/technotes/guides/visualvm/heapdump.html

在做这类事情时,使用您最喜欢的 Java IDE 查看 Java 源代码的相关部分很有用。

【讨论】:

  • 从 VisualVM download.oracle.com/javase/6/docs/technotes/guides/visualvm/… 开始...或查看上面在评论中提供的 Google 搜索结果。
  • 谢谢!我没有意识到我的机器上一直有这个......好吧,看起来 BufferedImages 是问题所在,我有 206 个 =O。但是我的所有对象都没有引用它们中的大多数!所以在我处理完它们后它们似乎会留下来......
  • 我查看了堆转储,对它们的唯一引用是 biimage、referent、bImg、bufImg 等。这些都不是我的代码的一部分。知道如何摆脱它们吗?
  • 检查参考链回到堆根。如果链中的至少一个引用没有保存在非 JDK 类的类或实例变量中,我会感到非常惊讶。即使是这种情况,也可能有一些 JDK 方法会在根处破坏链,从而允许对所有内容进行 GC。
  • 为了清楚起见,您只需要将链断开回到 GC 根...某处...对象变得无法访问,并且有资格进行垃圾回收。
【解决方案2】:

您的程序是网络应用程序吗?或者您正在开发类似 JRE 的应用程序?您如何加载图片?

在基于 Web 的应用程序中,我会使用 CSS-Sprite 图像来解决我的问题,因为它会切断几个 HTTP 请求并提高带宽使用率和负载时的内存使用率。

在 JRE 应用程序中,应该有一种以相同方式使用图像精灵的方法,加载图像精灵的 400x400 偏移量以减少 BufferedImage 对象的使用并提高性能。

【讨论】:

  • 这是一个普通的JRE程序。从文件加载的图像使用 Toolkit.getDefaultToolkit().createImage(imageName)。 BufferedImages 是使用标准 BufferedImage 构造函数创建的。不太清楚你对图像精灵的意思,你有一个例子吗?
  • 你可以在这个网站上查看 sprite 技术的基于 web 的版本:css-tricks.com/css-sprites 我仍然没有找到在基于 JRE 的程序中实现这种技术的任何方法,也许Stephen C 的领导可能会有所帮助。
猜你喜欢
  • 2015-11-17
  • 1970-01-01
  • 1970-01-01
  • 2019-11-12
  • 2012-05-25
  • 1970-01-01
  • 2015-10-14
  • 2013-07-18
  • 2013-07-11
相关资源
最近更新 更多