android createBitmap OOM when((freeMemory> bitmapSize)&&(nativeFreeHeap< bitmap size))

时间:2011-06-30 22:03:12

标签: android bitmap out-of-memory

在Android 2.2上,以下程序生成OOM。总之,该计划执行以下操作:

  1. 分配一个大型数组,要求本机堆增长到接近其最大大小。
  2. Garbage收集数组。
  3. 尝试创建大小大于剩余本机空闲堆的位图。
  4. 为什么这会因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 个答案:

答案 0 :(得分:1)

我认为你已经深入到了无证件行为 - 你无法指望在不同的Android版本或设备上保持一致的任何答案。

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

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