【问题标题】:OutOfMemoryError in j2me applicationj2me 应用程序中的 OutOfMemoryError
【发布时间】:2009-07-01 18:38:52
【问题描述】:

我在 J2ME 应用程序中收到 OutOfMemoryException

如何找到导致此错误的原因?以及如何防止出现此错误?

我发出一个 http 请求。当请求未完成时,屏幕会显示加载图像(就像浏览器在页面加载时显示的那样)。这是通过创建一个图像并重新绘制屏幕来完成的。

创建图像 1 -> 重绘 -> 创建图像 2-> 重绘-> 创建图像 3 -> 重绘 -> 创建图像 1-> 重绘 -> .

我注意到(使用 wtk 内存监视器)这消耗了太多没有被垃圾回收的内存。

然后我尝试创建一个类似于图像池的类。此类创建所有图像,然后显示它们。

创建图像 1 -> 创建图像 2-> 创建图像 3 -> 重绘 -> 重绘 -> 重绘 -> 重绘 -> 重绘 -> .

第二种情况消耗的内存似乎没有第一种情况多。 (使用 wtk 内存监视器)。

但是,我认为(不确定是否是这样)这两种方法都导致了这个OutOfMemoryException

【问题讨论】:

  • 你是在调试器中运行它吗?
  • 我正在设备中运行。当我使用模拟器运行时,我没有收到此错误。
  • 您使用的是什么 IDE(如果有)?它可能有一个分析器,您可以使用它来查找正在使用这么多内存的原因。
  • 您使用的是什么设备?此设备上有多少内存可供 j2me 程序使用?
  • @Janusz 我使用的是诺基亚 2660。规格是 16MB 闪存 + 2MB RAM。

标签: java java-me mobile


【解决方案1】:

错误的原因是内存不足。很抱歉说的很明显,但你问了:-)

为了诊断确切的问题,需要一些源代码。

您还应该寻找在循环中进行递归方法调用或分配内存的代码部分。递归调用通常会生成 StackOverflowException,但值得一看。不过,在循环内分配内存会很快导致 OutOfMemoryError。

【讨论】:

  • 我知道是内存不足。但是应用程序很简单,应该不会有这个问题。
  • 这就是我要求源代码的原因。我说这是“缺乏记忆”的舌头。
【解决方案2】:

您的OutOfMemoryException 在移动设备上显示图像时是由于堆内存不足,这可以通过。以System.gc(); 运行垃圾收集器,但不幸的是它在 J2ME 中不起作用。

所以,我们可以在这里使用

Runtime.getRuntime().gc();

而不是

System.gc();

【讨论】:

    【解决方案3】:

    这个问题一般在模拟器内存​​不足时出现。

    原因:

    1. 您使用的图片过多。
    2. 您正在初始化太多对象。
    3. 您的设备内存不足。

    解决方案:

    1. 您可以按降序加载图像。
    2. 您可以使用gc() 函数删除垃圾收集。
    3. 如果某些对象未使用,则将 null 分配给该对象。
    4. 不要在循环中初始化对象。
    5. 不要一次又一次地创建相同的图像。如果您想使用相同的图像,只需使用相同图像的引用(如果您在不同的类中创建相同的图像,则可能会出现此问题)

    【讨论】:

      【解决方案4】:

      根据设备的限制,创建和保留 3 张全屏图像可能会出现问题。

      您的三张“正在加载”的图片有很大不同吗?还是它们在很大程度上是相同的图像,只是在图像之间只有一小部分不同(例如,所有图像都是大白场中间的“纺车”的各种图像)?

      如果您可以避免让图像 1 成为您正在显示的完整图像,而图像 2 和 3 是可以在图像 1 之上绘制的小图像,那么您可以节省大量内存。

      即:在开头创建图像1-3。然后,在 repaint() 上,始终绘制图像 1,以及可选的图像 2 或图像 3,具体取决于动画中的步骤。

      【讨论】:

      • 所有图像都很小(16x16,~460bytes),我正在传递要重新绘制的位置:repaint(100,73,16,16)。而且我使用的是 8 张图片,而不是 3 张。
      • 你的http请求返回的内容有多大?这可能是导致您的记忆错误的原因吗?如果您确定内存问题是图像创建/保存/绘画,您可以尝试使用 Sprite 类。听起来它类似于您为场景 #2 创建的类,并且可能针对移动设备的严格限制进行了优化。
      • http 响应很小。我确定图像不是 only 问题。讨厌维护别人的代码!我会检查这个 Sprite 类。
      【解决方案5】:

      只创建一次图像并在任何你想要的地方重复使用它们,并在需求结束后立即将它们的引用设为 null。这将使它们被垃圾收集。

      不要创建任何不需要的变量或对象(尤其是图像对象)。

      您可以通过调用System.gc() 显式启动垃圾回收。但是经常调用这个可能会影响性能

      【讨论】:

        【解决方案6】:

        OutOfMemoryException 出现在 j2me 中是因为变量在使用完成后没有释放其内存。我们可以显式地释放变量的内存。

        任务完成后释放该变量的内存。尝试不要一次加载所有图像为此进行延迟加载。与其他变量相比,图像占用较大空间。所以使用低质量的图像,也不要在应用程序中使用自定义字体使用系统字体。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多