图像和数组存储中的"java.lang.OutOfMemoryError: Java heap space"

4
我目前正在使用Java(Applet)进行图像处理演示。我遇到的问题是我的数组太大,导致出现“java.lang.OutOfMemoryError: Java heap space”错误。
我运行的算法创建了一个NxD浮点数组, 其中:N是图像中像素的数量,D是每个像素的坐标加上每个像素的颜色空间组件(通常为灰度的1或RGB的3)。每次迭代算法时,它都会创建一个这样的NxD浮点数组并将其存储供以后在向量中使用,以便Applet的用户可以查看单个步骤。
我的客户希望该程序能够加载一个500x500的RGB图像并运行作为上限。每次运行大约有12到20个迭代,因此我需要以某种方式存储一个12x500x500x5浮点数。
是否有一种方法可以处理所有这些数据,如果可能的话,如何处理?
例如,我正在加载一个512x512的灰度图像,甚至在第一次迭代完成之前,我就已经用完了堆空间。它指向的代码行是:
Y.add(new float[N][D])
其中Y是一个Vector,N和D如上所述。这是代码使用该行的第二个实例。
编辑:正如我提到但忘记更正的那样,上限应该约为:20 + x 500 x 500 x 5(20个迭代,500宽度,500高度,5个维度(其中3来自RGB和2为坐标(坐标移动,像素也随之移动,因此我需要记录值,这些可以是小数))(约100000000字节)。

1
为什么要使用浮点数?我的意思是,一个字节不够吗? - Pablo Grisafi
我在我的编辑中解释了。对此感到抱歉。 - user357777
4个回答

3

我认为你不能将这个做成一个Applet。(浏览器可能有分配给applet的内存设置,但我不知道。)

如果你可以使用Java Web Start,我会建议你使用它。你可以设置所需的内存大小:

<j2se version="1.4+" initial-heap-size="100M" max-heap-size="200M"/>

使用Web Start的优点是用户无需配置其浏览器。
编辑:Java控制面板确实有用于小程序的内存设置。请参见如何使用更多内存启动Java小程序? 但是,除非您只有少数几个客户不介意更改其Java设置(并且他们具有适当的权限和技能),否则这不是一个良好的用户体验。使用Web Start,您可以在JNLP描述符中设置所有内容,然后就可以开始了。

Webstart确实是一个好选择。对于OP:这里有一个可能有用的迁移指南:http://java.sun.com/javase/6/webnotes/deploy/applet-migration.html - BalusC
感谢您的反馈。我会尽快深入研究这个问题。 - user357777
幸运的是,我不需要迁移应用程序。我仍然将它作为一个框架,并在应用程序完成最后的修饰后研究这个 Web Start。 - user357777

-1

你尝试过增加初始堆大小以及设置最大堆大小吗?

java -Xms<initial heap size> -Xmx<maximum heap size>

例如

java -Xms256M -Xmx512M

默认值相当保守,而且很小,因此您肯定希望尝试并玩弄堆大小设置。


2
这不是我的踩票,但OP提到代码是一个小程序——你无法控制分配的内存。 - mdma
感谢澄清 - 一直想知道为什么我被踩了。不知道你不能控制小程序的内存设置 - 知道了真好! - ssahmed555

-1

1) 12x500x500x5个浮点数大约需要60 MB,加上一些开销。如果您正确配置JVM堆(例如-Xmx500M),在合理的计算机上应该没有问题保留所有内存空间。另一方面,如果您将其作为小程序运行,则应进行一些设置(例如,我找到了this链接,适用于Java 6更新10及以上版本)。

2)关于每个像素的数据格式,您并没有提供太多信息。也许您可以使其更紧凑。为什么每个像素需要5个浮点数?您可以将RGB值存储为3个字节,并且似乎不需要存储像素位置,因为2维数组中的位置已经指示了位置。


在小程序中,您无法从服务器端控制内存使用情况。该链接显示客户端必须自行配置它们,这对“用户体验”来说并不是很好。 - BalusC
@BalusC:谢谢,你说得对。我用一个更有用的链接替换了它。 - Eyal Schneider

-1
要将堆空间大小增加到默认的64MB之外,您需要使用-Xmx参数执行应用程序(对于小程序,请在Java运行时设置中添加,在任何操作系统的管理工具中都可以找到)。但是,如果这将成为Web应用程序,则不太可能在许多最终用户机器上进行修改,因此这不是一个选项。
我想了解一下x维数组中的存储情况。您究竟存储了什么?为什么是4字节浮点数?未压缩的原始图像通常存储在WIDTHxHEIGHT数组中,其中每个单元格包含一个颜色对象(例如,3个描述RGB空间的shorts)。对于500x500的图像,这样的数组将需要500 * 500 * 3(颜色维数)* 2(short的字节数)= 1,500,000字节,远少于500 * 500 * 5(仍然没有弄清楚为什么是5,可能您存储颜色+坐标)* 4(float中的字节数)= 5,000,000字节。
请注意,正是出于这个原因,才开发了压缩算法(如JPEG),以便您不必为每个图像保留1.5MB的内存。
至于迭代,但主要是为了随后的存储,除非您想陷入编写类似MPEG格式的麻烦中,否则没有什么可说的,因为您只需要保存帧之间的更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接