On Android 2.2, the following program produces an OOM. In summary, the program does the following:
- Allocates a big array that requires native heap to grow close to its maximum size.
- Garbage collects the array.
- Attempts to create a bitmap of size larger than the remaining native free heap.
Why does this fail with an OOM? It's as if the native heap will only allocate memory for bitmaps in memory previously unallocated.
The output appears below the program. Thanks in advance.
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());
}
}
Here's the output:
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)