重启应用程序时出现内存不足错误(Android)

时间:2012-12-29 23:22:38

标签: android memory-leaks andengine

我正在开发一款使用5张900x600左右大图像的游戏。当我退出游戏(按后退按钮)然后尝试启动游戏时,我收到以下错误:

12-29 15:59:16.633: E/AndroidRuntime(18642): FATAL EXCEPTION: GLThread 17
12-29 15:59:16.633: E/AndroidRuntime(18642): java.lang.OutOfMemoryError: (Heap  Size=20423KB, Allocated=3473KB, Bitmap Size=77KB)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.util.GLHelper.getPixelsARGB_8888(GLHelper.java:165)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.util.GLHelper.getPixels(GLHelper.java:41)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.util.GLState.glTexImage2D(GLState.java:641)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.texture.bitmap.BitmapTexture.writeTextureToHardware(BitmapTexture.java:120)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.texture.Texture.loadToHardware(Texture.java:137)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.texture.TextureManager.updateTextures(TextureManager.java:254)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.engine.Engine.onDrawFrame(Engine.java:621)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at org.andengine.opengl.view.EngineRenderer.onDrawFrame(EngineRenderer.java:105)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1363)
12-29 15:59:16.633: E/AndroidRuntime(18642):    at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1118)

这真是令人困惑,因为我在应用程序被销毁之前卸载了所有纹理。我知道这5张图片导致错误,因为当我完全跳过加载它们时,我没有收到任何错误。为了确保卸载所有纹理,我在卸载后立即加载纹理。然后我退出并重新启动游戏但收到同样的错误。纹理也没有任何静态引用。我还使用了MAT来看看我在游戏中使用了多少内存,并注意到我只使用了2.5MB,所以我不知道为什么错误是“堆大小= 20MB”。我设法暂时解决错误的唯一方法是包含

system.exit(0);

我知道我不应该使用,但我完全没有想法。

编辑:我确保正在卸载纹理。我在游戏中有一个按钮可以卸载所有纹理。当我按下它时,所有的纹理都变成黑色,我假设它卸载了纹理。我在卸载纹理时使用的一般方法就是说

someTexture.unload();

这是一个andEngine方法。我不确定除此之外会发生什么。

编辑2:我在一个名为onCreateResources()的方法中加载纹理,然后将它们卸载到onDestroy()上。这是我操纵纹理的唯一两个地方。

2 个答案:

答案 0 :(得分:2)

如果我从Android API中正确回忆: 按后退按钮并不一定意味着onDestroy()。 Android操作系统会为您处理garbarge集合,并在需要时调用onDestroy()(例如,当您按下后退按钮后启动了更多应用程序时)。

但是,有一些ROMS允许您通过长按后退按钮来“杀死”应用程序。

你可以尝试从onStop()卸载纹理并报告回来吗?

编辑:没看到Shark的回复。 OnPause()也有效 - 相同的概念......实际上onPause()总是在OnStop()之前被调用,所以它可能是一个更好的解决方案。

答案 1 :(得分:2)

垃圾收集器不会立即释放未使用的对象内存,因此如果您尝试在短暂后重新加载新的位图,则没有可用的空闲内存。

也许您应该使用WeakReference:JVM必须在抛出OutOfMemoryException之前释放WeakReference对象。可以在此处找到一个示例:http://developer.android.com/training/displaying-bitmaps/display-bitmap.html