JavaME - LWUIT图像占用了所有内存

时间:2009-09-07 16:26:17

标签: java-me midlet lwuit

我正在使用LWUIT编写MIDlet,图像似乎耗尽了大量的内存。我使用的所有图像都是PNG,并打包在JAR文件中。我使用标准的Image.createImage(URL)方法加载它们。应用程序有许多表单,每个表单都有一些标签和按钮,但我相当确定只有活动表单保存在内存中(我知道它不是很值得信赖,但Runtime.freeMemory()似乎确认这一点)。

该应用程序在240x320分辨率下运行良好,但将其移至480x640并使用适当大的UI图像开始导致出现内存不足错误。除其他外,应用程序的功能是下载远程图像。该应用程序似乎工作正常,直到它到达这一点。下载几个PNG并返回主菜单后,遇到内存不足错误。当然,我查看了主菜单使用的内存量,这非常令人震惊。这只是带有图像和四个按钮的两个标签。每个按钮都有三个用于style.setIcon,setPressedIcon和setRolloverIcon的图像。图像的大小范围为15到25KB,但删除了每个按钮使用的三个图像中的两个(总共8个图像),Runtime.freeMemory()显示内存使用量减少了1MB。

我看到它的方式,我要么有很多内存泄漏(我不认为我这样做,但内存泄漏并不是很容易被人追踪),我正在做一些非常错误的事情图像处理或者确实没有问题,我只需要缩小。

如果有人有任何提供的见解,我将不胜感激。

5 个答案:

答案 0 :(得分:2)

移动设备的内存通常非常低。所以你必须使用一些技巧来保存和使用记忆。

我们在一个项目中遇到了同样的问题,我们就这样解决了。

下载图片: 在您放置图像的位置创建缓存。如果你需要一个图像,检查它是否在缓存图中,如果它没有下载并放在那里,如果是,请使用它。如果内存已满,请删除缓存中最旧的图像,然后重试。

其他资源图片: 只要你能看到它们就把它们留在内存中,如果你看不到它们,打破引用,gc会为你做清理。

希望这有帮助。

答案 1 :(得分:1)

这里可能会发生一些事情:

  • 您可能已经看过垃圾收集前使用的内存,这与您应用使用的实际内存不符。
  • 您正在运行的某些第三方代码可能正在汇集一些内部数据结构以最小化分配。虽然汇集是一种可行的策略,但有时它看起来像是泄漏。在这种情况下,查看是否有API来“关闭”或“处置”您不需要的对象。
  • 最后,你可能真的有泄漏。在这种情况下,您需要获取有关模拟器VM中发生的更多详细信息(但请记住,它不一定与手机VM相同)。

确保您的模拟器使用JRE 1.6作为后备JVM。如果您需要使用来自erlyer JDK的运行时库,请使用-Xbootclasspath:<path-to-rt.jar>

然后,在您的应用程序进入您想要查看的状态后,执行%JAVA_HOME%\bin\jmap -dump:format=b,file=heap.bin <pid>(如果您不知道流程的ID,请使用jps

现在您已经获得了JVM堆的转储。您可以使用jhat(JDK附带,有点难以使用)或某些第三方分析器(我的偏好是YourKit - 分析它 - 它是商业的,但它们有时间限制的eval许可证)< / p>

答案 2 :(得分:1)

我在Java DTV上与LWUIT有类似的问题。当你不再需要它们时,你是否尝试刷新图像(getAWTImage()。flush())?

答案 3 :(得分:1)

尽可能使用EncodedImage和资源文件(资源文件默认使用EncodedImage。请阅读javadoc。其他注释也是正确的,你需要实际观察内存量,甚至高RAM Android / iOS设备使用多个图像时内存不足。

避免缩放,有效消除EncodedImage

答案 4 :(得分:0)

你有没有想过这样的事实,即可能多次从JAR加载相同的图像会导致创建许多单独的图像对象(具有相同的内容),而不是重复使用每个单独的图像一个实例?这是我的第一个猜测。