6

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

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

在我看来,我要么有很多内存泄漏(我认为我没有,但内存泄漏并不完全知道很容易追踪),我在图像处理或真的没有问题,我只需要按比例缩小。

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

4

5 回答 5

2

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

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

对于下载的图像:在放置图像的位置进行缓存。如果您需要图像,请检查它是否在缓存映射中,如果没有,请下载并将其放在那里,如果是,请使用它。如果内存已满,请删除缓存映射中最旧的图像并重试。

对于其他资源图像:只要您可以看到它们,就将它们保留在内存中,如果您看不到它们,请中断引用,gc 将为您进行清理。

希望这可以帮助。

于 2010-12-08T11:18:30.390 回答
1

There are a few things that might be happening here:

  • You might have seen the memory used before garbage collection, which doesn't correspond to the actual memory used by your app.
  • Some third party code you are running might be pooling some internal datastructures to minimize allocation. While pooling is a viable strategy, sometimes it does look like a leak. In that case, look if there is API to 'close' or 'dispose' the objects you don't need.
  • Finally, you might really have a leak. In this case you need to get more details on what's going on in the emulator VM (though keep in mind that it is not necessarily the same as the phone VM).

Make sure that your emulator uses JRE 1.6 as backing JVM. If you need it to use the runtime libraries from erlyer JDK, use -Xbootclasspath:<path-to-rt.jar>.

Then, after your application gets in the state you want to see, do %JAVA_HOME%\bin\jmap -dump:format=b,file=heap.bin <pid> (if you don't know the id of your process, use jps)

Now you've got a dump of the JVM heap. You can analyze it with jhat (comes with the JDK, a bit difficult to use) or some third party profilers (my preference is YourKit - it's commercial, but they have time-limited eval licenses)

于 2010-02-28T02:34:33.200 回答
1

尽可能使用EncodedImage和资源文件(EncodedImage默认情况下使用资源文件。请阅读 javadoc。其他评论也是正确的,您需要实际观察内存量,即使是高 RAM Android/iOS 设备也会很快耗尽内存图片。

避免缩放,这有效地消除了EncodedImage.

于 2012-02-17T09:18:31.430 回答
1

我在 Java DTV 上遇到了与 LWUIT 类似的问题。当您不再需要图像时,您是否尝试过刷新图像(getAWTImage().flush())?

于 2010-06-08T22:59:01.123 回答
0

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

于 2009-09-08T22:38:16.113 回答