【问题标题】:Android app crash out of memory on relaunchAndroid应用程序在重新启动时内存不足
【发布时间】:2012-06-18 12:25:16
【问题描述】:

所以我遇到了一个由大位图引起的臭名昭著的 oom 错误。但我已经设法解决了大部分问题。当我单击返回并关闭应用程序然后立即启动应用程序时,剩下的唯一问题发生了。然后应用程序将崩溃,给我一个 oom(内存不足)错误。如果我单击主页,则不会发生这种情况。

为什么会这样?我的猜测是 GC 还没有完成清理,现在我在旧数据仍然存在的时候启动它。当然,它不是一个新应用,所以旧版本和新版本的应用内存限制相同。

关于这个问题的任何意见和可能的解决方案都会很棒。

我尝试过的:

关于我使用过的所有位图下载:

BitmapFactory.Options op = new Options();
op.inPurgeable = true;
bmImg = BitmapFactory.decodeStream(is,null,op);

使图像的尺寸宽度 x 高度更小(以 kb 为单位的大小大致相同)。

错误日志片段:

06-25 04:29:28.917: E/AndroidRuntime(8819): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:460)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:715)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.content.res.Resources.loadDrawable(Resources.java:1713)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.widget.ImageView.<init>(ImageView.java:122)
06-25 04:29:28.917: E/AndroidRuntime(8819):     at android.widget.ImageView.<init>(ImageView.java:112)
06-25 04:29:28.917: E/AndroidRuntime(8819):     ... 23 more

编辑: 所以有两件事为我解决了这个问题。

  1. 在我的主要活动的 ondestroy() 中清除我的数据库并将大图像设置为 null。
  2. 缩小大图像。

但这只是提出了同样的基本问题,如果调用 onDestroy(),为什么我的活动在打开新活动之前没有正确关闭?我还看到我的活动在关闭后很长一段时间内继续运行。这可能与问题有关吗?我该如何追查造成这种情况的原因?

Edit2:罪魁祸首似乎是我的 LruCache。我使用了一个未在 ondestroy() 中清除的静态 lrucache。当应用程序重新启动时,lrucache 中的所有图像仍然存在,这会导致问题。我仍然想知道为什么这只是重启时的问题?当我在关闭之前返回主要活动时,这难道不是一个问题吗?

【问题讨论】:

标签: android bitmap out-of-memory


【解决方案1】:

我遇到了同样的问题,通过强制关闭进程解决了。这可以通过重写 onDestroy() 来完成。使用这个:

@Override
public void onDestroy(){
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> pids = am.getRunningAppProcesses();
    for (int i = 0; i < pids.size(); i++) {
        ActivityManager.RunningAppProcessInfo info = pids.get(i);
        if (info.processName.equalsIgnoreCase(context.getPackageName())) {
            android.os.Process.killProcess(info.pid);
        }
    }
    super.onDestroy();
}

【讨论】:

  • 这可能会起作用,但我想我会尝试找到导致我的应用无法正常关闭的参考。
  • 经过一些阅读(包括普通软件),我不会朝这个方向发展。这可能会导致各种其他麻烦。
  • 我理解您的担忧,但我还没有找到更好的解决方案。
  • 我更喜欢“Android”方式,从而让系统关闭我的应用程序。我发现当您的应用程序关闭时静态变量不会被清除。因此,对于我的问题,我将确保在 ondestroy() 中将这些变量设置为 null
【解决方案2】:

嘿,请检查我对同一问题的回答:bitmap size exceeds Vm budget error android

并且在处理这样的位图时也总是尝试使用最大选项:

        final Options options = new Options();
        options.outHeight = (int) scaleHeight; // new smaller height
        options.outWidth = (int) scaleWidth;   // new smaller width
        options.inScaled = true;
        options.inPurgeable = true;

        // to scale the image to 1/8
        options.inSampleSize = 8;
        bitmap = BitmapFactory.decodeFile(imagePath, options);

这可能会解决您的问题。

【讨论】:

  • 我已经在使用 inPurgeable。 inSampleSize 会降低质量,这不是一个选项。我需要它进来的大小的图像。
  • 如果你的图片非常大,比如 2 到 3 mb,那么加载图片会导致这个错误。图像的大小是多少?检查您的代码是否有任何内存泄漏,这也可能是问题。
  • mdpi 为 900 x 900 像素和 ~93kb,hdpi 放大
  • 如果图像不是很大,则检查WeakReference。当你处理位图时,总是在处理完位图后立即调用它的 recycle() 方法。
  • 我对从网络等下载的所有图像使用 lrucache。当需要创建大轮图像时,问题发生在应用程序重新启动时。
【解决方案3】:

罪魁祸首似乎是我的 LruCache。我使用了一个未在 ondestroy() 中清除的静态 lrucache。当应用程序重新启动时,lrucache 中的所有图像仍然存在,这会导致问题。我仍然想知道为什么这只是重启时的问题?当我在关闭之前返回主要活动时,这不应该也是一个问题吗?

尽管如此,我对这个问题的临时/永久修复是清除 ondestroy() 中的所有静态引用,但也使用较小尺寸的图像。这似乎解决了我所有的问题,因为我也找不到任何内存泄漏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-25
    • 1970-01-01
    • 2012-11-30
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 2012-10-04
    相关资源
    最近更新 更多