How can I fix frequent Out Of Memory Errors on And

2019-04-14 20:03发布

I test a mobile app and have been struggling with constant crashes of the app when I use an Android emulator. I have no problem on physical Android devices, but emulators crash several times per day. The app will crash quite consistently once I find a crash-prone part of the app's "workflow". But exactly where in the app will trigger a crash seems to vary from version to version.

Here is the crash report:

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)

And here is a screenshot of my emulator settings:

emulator settings

I have tried changing the RAM and VM Heap and Internal Storage settings without much luck. In fact, the emulator launcher will start to complain if I set the RAM too high.

2条回答
一夜七次
2楼-- · 2019-04-14 20:38

You either truly have run out of heap space, or the heap is sufficiently fragmented that Android cannot allocate whatever you are requesting. This will happen on production devices as well, and so treating this as an emulator issue is a mistake IMHO.

I'd start by doing more testing with the 4.x emulator. Partly, that will give you better crash information, including how large of an allocation failed. Partly, it will give you substantially better results when using MAT to figure out where your heap is going.

There are umpteen zillion questions and answers here on StackOverflow regarding OutOfMemoryError with bitmap allocation. You may wish to browse through some. They will point you in the same basic directions:

  • On Android 3.0+, use inBitmap on the BitmapOptions that you pass to BitmapFactory, to reuse existing memory as opposed to allocating new memory

  • recycle() your Bitmap objects when you are done with them

  • Be generally careful about your memory allocations, as Android's garbage collector is non-compacting, so eventually you will be incapable of allocating large blocks of memory again

  • Use MAT to see if you are leaking memory somewhere that is contributing to your problem

And so on.

查看更多
聊天终结者
3楼-- · 2019-04-14 20:53

Have a look at this Developer's Guide.

Use this workflow while decoding bitmap from external source:

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;
}

The important part is the inJustDecodeBounds.

查看更多
登录 后发表回答