在使用android的createBitmap函数时,当可用内存大于位图大小并且本地空闲堆内存小于位图大小时,可能会出现OOM(Out of Memory)错误。

3
在Android 2.2上,以下程序会产生OOM。简要来说,该程序执行以下操作:
  1. 分配一个需要增长到接近最大大小的本地堆的大数组。
  2. 垃圾回收该数组。
  3. 尝试创建一个大小超过剩余本地空闲堆的位图。
为什么会因为OOM而失败呢?这就像本地堆只会为以前未分配内存的位图分配内存一样。
程序输出如下。提前致谢。
public class OomTest extends Activity {
    private static final String OOM_TEST = "OomTest";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        printDiag();
        Log.i(OOM_TEST, "Allocating big int array.");
        int[] bigIntArray = new int[11000000];
        printDiag();
        bigIntArray = null;
        Log.i(OOM_TEST, "Garbage collecting.");
        System.gc();
        printDiag();
        Log.i(OOM_TEST, "Creating 4 meg bitmap bitmap.");
        Bitmap bitmap = Bitmap.createBitmap(1000, 1000, Config.ARGB_8888);
        printDiag();        
        Log.i(OOM_TEST, "Done.");
    }

    private void printDiag() {
        Log.i(OOM_TEST, "maxMemory: " + Runtime.getRuntime().maxMemory());
        Log.i(OOM_TEST, "totalMemory: " 
              + Runtime.getRuntime().totalMemory());
        Log.i(OOM_TEST, "freeMemory: " 
              + Runtime.getRuntime().freeMemory());
        Log.i(OOM_TEST, "nativeHeapSize: " 
              + android.os.Debug.getNativeHeapSize());
        Log.i(OOM_TEST, "nativeHeapAllocatedSize: " 
              + android.os.Debug.getNativeHeapAllocatedSize());
        Log.i(OOM_TEST, "nativeHeapFreeSize: " 
              + android.os.Debug.getNativeHeapFreeSize());
    }
}

以下是输出结果:
I/ActivityManager( 2501): Start proc com.example.android.oomTest for activity
    com.example.android.oomTest/.OomTest: pid=25242 uid=10031 gids={1015}
I/OomTest (25242): maxMemory: 50331648
I/OomTest (25242): totalMemory: 2953200
I/OomTest (25242): freeMemory: 479512
I/OomTest (25242): nativeHeapSize: 3600384
I/OomTest (25242): nativeHeapAllocatedSize: 3585800
I/OomTest (25242): nativeHeapFreeSize: 14584
I/OomTest (25242): Allocating big int array.
D/dalvikvm(25242): GC_FOR_MALLOC freed 634 objects / 51344 bytes in 48ms
I/dalvikvm-heap(25242): Grow heap (frag case) to 44.573MB for 44000016-byte allocation
D/dalvikvm(25242): GC_FOR_MALLOC freed 34 objects / 1992 bytes in 60ms
I/OomTest (25242): maxMemory: 50331648
I/OomTest (25242): totalMemory: 46997472
I/OomTest (25242): freeMemory: 575224
I/OomTest (25242): nativeHeapSize: 3600384
I/OomTest (25242): nativeHeapAllocatedSize: 3578408
I/OomTest (25242): nativeHeapFreeSize: 23560
I/OomTest (25242): Garbage collecting.
D/dalvikvm(25242): GC_EXPLICIT freed 65 objects / 44002952 bytes in 52ms
I/OomTest (25242): maxMemory: 50331648
I/OomTest (25242): totalMemory: 46997472
I/OomTest (25242): freeMemory: 44576440
I/OomTest (25242): nativeHeapSize: 3600384
I/OomTest (25242): nativeHeapAllocatedSize: 3575784
I/OomTest (25242): nativeHeapFreeSize: 24600
I/OomTest (25242): Creating 4 meg bitmap bitmap.
E/dalvikvm-heap(25242): 4000000-byte external allocation too large for this process.
E/GraphicsJNI(25242): VM won't let us allocate 4000000 bytes
D/AndroidRuntime(25242): Shutting down VM
W/dalvikvm(25242): threadid=1: thread exiting with uncaught exception (group=0x4001d7d0)
E/AndroidRuntime(25242): FATAL EXCEPTION: main
E/AndroidRuntime(25242): java.lang.OutOfMemoryError: bitmap size exceeds VM budget
E/AndroidRuntime(25242):        at android.graphics.Bitmap.nativeCreate(Native Method)
E/AndroidRuntime(25242):        at     android.graphics.Bitmap.createBitmap(Bitmap.java:468)
E/AndroidRuntime(25242):        at com.example.android.oomTest.OomTest.onCreate(OomTest.java:26)
1个回答

1

我认为你已经深入到未记录的行为中了 - 你不能指望在不同的Android版本或设备上得到一致的答案。

我的猜测是系统授予您的应用程序最大进程大小。进程大小包括dalvik堆和本地堆(当然还有一些开销)。您已将dalvik堆扩展到最大值。垃圾回收在dalvik堆中创建了空间,但所有进程的空间都分配给了dalvik堆,因此本地堆中没有足够的空间来容纳位图对象。

我相当确定这种行为在以前(或其他?)的Android版本中有所不同,其中dalvik堆无法扩展到总进程大小限制的约一半。


我可以确认他的行为在不同的Android设备上有所不同。在某些设备上,我遇到了为多个位图分配空间的许多麻烦,而在其他设备上则完全正常。 - Austyn Mahoney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接