在Android上的"Out of memory"错误

22 浏览
0 Comments

在Android上的"Out of memory"错误

我正在开发一个Android游戏应用程序,其中我有大约15个屏幕。当我连续游戏时,会随机出现内存不足的错误,有时在第15个屏幕,有时在第12个屏幕左右。\n此外,请查看下面的XML代码,其中包含一个屏幕的内容。\n日志记录:\n05-16 12:22:18.989: E/GraphicsJNI(6745): VM无法分配2225664字节\n05-16 12:22:18.999: E/AndroidRuntime(6745): 致命错误: Java.lang.OutOfMemoryError:位图大小超过VM预算\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.Bitmap.nativeCreate(Native Method)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.Bitmap.createBitmap(Bitmap.java:477)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.Bitmap.createBitmap(Bitmap.java:444)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.Bitmap.createScaledBitmap(Bitmap.java:349)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:498)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:473)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:336)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.content.res.Resources.loadDrawable(Resources.java:1709)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.content.res.Resources.getDrawable(Resources.java:581)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.view.View.setBackgroundResource(View.java:7533)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在com.ssn.myapp.NumbersLevel3.onCreate(NumbersLevel3.java:173)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:2832)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.ActivityThread.access$1600(ActivityThread.java:117)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.os.Handler.dispatchMessage(Handler.java:99)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.os.Looper.loop(Looper.java:130)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在android.app.ActivityThread.main(ActivityThread.java:3683)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在java.lang.reflect.Method.invokeNative(Native Method)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在java.lang.reflect.Method.invoke(Method.java:507)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)处\n05-16 12:22:18.999: E/AndroidRuntime(6745): 在dalvik.system.NativeStart.main(Native Method)处

0
0 Comments

在Android上出现内存不足错误是因为当你的activity被销毁时,你的图片没有被释放。你可以参考这个答案以及这个链接

我认为我们没有必要关注GC何时执行的细节,因为我们无法控制GC何时被调用。即使调用gc()也不能保证进行垃圾回收。根据System.gc()文档,内存已经超过了限制,GC会自动收集所有未使用的位图,所以我们必须自己删除它。

向虚拟机指示现在是运行垃圾回收器的好时机。请注意,这只是一个提示。不能保证垃圾回收器实际上会运行。

在开发分配大型对象的应用程序时,我会关注以下几点:

  1. 在分配大型对象后,当退出该对象的生命周期范围后,我是否在后续活动中看到它被GC回收?可以通过运行adb shell中的dumpsys meminfo来轻松检查。你可以在取消分配后检查内存是否被正确地垃圾回收,通常会出现大的峰值和随后的下降。
  2. 检查这个大型对象是否有一个明确的GC路径。你可以通过转储hprof并在内存分析器中检查该对象的引用路径来实现。如果有路径,那么GC会很聪明地进行回收。
  3. 在分配这个大型对象后,我是否有足够的堆内存来执行后续的活动?如果对象太大,GC可能没有足够快地回收它(这实际上与你的观点有关),并且后续活动中的内存消耗与先前活动的剩余内存结合在一起可能导致内存不足错误。设置一个明确的GC路径并将其设置为null将有助于确保该对象得到适当的GC。我承认这是个问题,但是我的观点是如果这成为问题,我们可能需要重新审视这个特定部分的设计,并看看是否可以对其进行任何优化。
  4. 根据需要在onDestroy中清理activity,并确保该Activity没有被其他对象引用,以便能够进行正确的垃圾回收。例如:我们经常传递activity context,忘记它将保持引用。像在位图上调用recycle()这样的操作也应该有所帮助。记住这些要点应该有助于在发生第3点时为其准备更多的空间。

希望这对你有所帮助。

不,那不是问题。应用程序超过了堆中分配的内存,因此出现OOM。"因为你的图片在activity销毁时没有被释放",这不是问题。

当我连续播放时,我会随机遇到内存不足的问题 OP只是这样说的。这就是为什么我认为图片没有被释放

你能更清楚地解释一下"图片没有被释放"这部分吗?从logcat来看,这是OOM。

根据logcat,OOM是因为位图大小超过了VM预算,这意味着没有足够的空间来为位图分配内存。当不使用位图时,你应该将其回收。当GC启动并且activity被暂停时,内存将被释放。此外,他应该有效地加载位图(图片)。如果图片太大,应该进行缩小。他应该在onResume()中加载位图,并在onPause()中回收。这样可以确保在GC启动和activity暂停时释放内存。

我也说了同样的事情。我说的是内存已经超过了限制,GC会自动收集所有未使用的位图,所以我们必须自己删除它。难道不是 Ragunandan 说的吗?

你不需要自己删除它。GC的工作就是释放内存,不需要调用System.gc()。看看我提供的链接System.gc()。他们说不能保证垃圾回收器实际上会被运行。

是的,垃圾回收器是由虚拟机运行的,那么System.gc()的意义在哪里?根据这里提出的问题?

OP说他运行了15个以上的活动。在每个活动中,他都会玩游戏。因此,如果没有调用System.gc(),内存将会增加。但不能保证System.gc()会被调用。所以我们需要清除或内存。这就是我说的。

你又错了。你不需要清除内存。垃圾回收的工作是由GC完成的,不需要调用System.gc()。你不应该调用System.gc()。虚拟机会在需要释放内存时运行GC。如果他有15个以上的活动,他应该在onResume()中加载图像,并在onPause()中取消绑定或回收。

0
0 Comments

在Android上出现“内存溢出错误”的原因可能是由于以下几个方面:

1. 未在使用时回收位图。自从Honeycomb版本以后,位图会一直停留在堆中。可以使用bitmaps.recycle();来回收位图。

2. 如果有高分辨率的图片,应该进行缩小处理。可以参考“Load a Scaled Down Version into Memory”这个主题来了解如何进行缩小处理。

3. 在每个加载位图的活动中,在onResume()中加载位图,在onPause()中回收位图。

4. 可以使用MAT分析器来分析和修复内存泄漏问题。可以参考以下视频:http://www.youtube.com/watch?v=_CruQY55HOk

5. 可以在清单文件的application标签下使用android:largeHeap。但是需要注意,增加堆大小会导致GC的频繁触发,从而导致应用程序的频繁暂停。因此,不应仅仅因为需要更大的堆而使用这个选项。

6. 大多数应用程序不需要使用android:largeHeap,而应该专注于减少整体内存使用以提高性能。

要在运行时查询可用的内存大小,可以使用getMemoryClass()或getLargeMemoryClass()方法。

0