【问题标题】:android createBitmap OOM when ((freeMemory > bitmapSize) && (nativeFreeHeap < bitmap size))android createBitmap OOM when ((freeMemory > bitmapSize) && (nativeFreeHeap < bitmap size))
【发布时间】:2011-09-26 08:44:50
【问题描述】:

在 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)

【问题讨论】:

    标签: android bitmap out-of-memory


    【解决方案1】:

    我认为您在这里深陷未记录的行为 - 您将无法指望在不同的 Android 版本或设备上获得一致的任何答案。

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

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

    【讨论】:

    • 我可以确认他的行为在不同的 Android 设备上有所不同。在某些设备上为多个位图分配空间时,我遇到了很多麻烦,但在其他设备上却可以正常工作。
    猜你喜欢
    • 2017-06-13
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 2011-11-09
    • 2012-01-01
    • 1970-01-01
    相关资源
    最近更新 更多