2

我测试了一个移动应用程序,并且在使用 Android 模拟器时一直在努力解决应用程序不断崩溃的问题。我在物理 Android 设备上没有问题,但模拟器每天崩溃几次。一旦我发现应用程序“工作流程”中容易崩溃的部分,该应用程序就会一直崩溃。但是,应用程序中触发崩溃的确切位置似乎因版本而异。

这是崩溃报告

Android: 2.3.7
Model: Full Android on x86 Emulator

java.lang.OutOfMemoryError: bitmap size exceeds VM budget
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525)
at our.app.util.OurAppFileManager.getBrandingImageFromSD(OurAppFileManager.java:104)
at our.app.MainScreen.onResume(MainScreen.java:150)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1150)
at android.app.Activity.performResume(Activity.java:3832)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2110)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2135)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1668)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)

这是我的模拟器设置的屏幕截图

模拟器设置

我尝试更改 RAM 和 VM 堆以及内部存储设置,但运气不佳。事实上,如果我将 RAM 设置得太高,模拟器启动器就会开始抱怨。

4

2 回答 2

4

你要么真的用完了堆空间,要么堆足够分散,Android 无法分配你请求的任何东西。这也将发生在生产设备上,因此将其视为模拟器问题是一个错误恕我直言。

我会先用 4.x 模拟器做更多的测试。在某种程度上,这将为您提供更好的崩溃信息,包括分配失败的大小。在某种程度上,当使用 MAT 来确定堆的去向时,它会给你带来更好的结果。

StackOverflow 上有无数关于OutOfMemoryError位图分配的问题和答案。您可能希望浏览一些。他们会为您指出相同的基本方向:

  • 在 Android 3.0+inBitmap上,使用BitmapOptions您传递给的BitmapFactory,以重用现有内存而不是分配新内存

  • recycle()完成后的Bitmap对象

  • 通常要小心你的内存分配,因为 Android 的垃圾收集器是非压缩的,所以最终你将无法再次分配大块内存

  • 使用 MAT 查看是否在导致问题的某处泄漏内存

等等。

于 2013-07-08T23:42:06.863 回答
2

看看这个开发者指南

从外部源解码位图时使用此工作流程:

private Bitmap decodeFile(File f, int reqHeight, int reqWidth){
    try {
        //Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);

        //Find the correct scale value. It should be the power of 2.
        int scale=1;
        while(o.outWidth/scale/2>=reqWidth && o.outHeight/scale/2>=reqHeight)
            scale*=2;

        //Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}

    return null;
}

重要的部分是inJustDecodeBounds

于 2013-07-09T05:12:57.657 回答