android runtime_error ai_generated true

java.lang.OutOfMemoryError: Failed to allocate a 41472012 byte allocation with 16777216 free bytes and 16MB until OOM, target footprint: 268435456, growth limit: 268435456

ID: android/outofmemoryerror-bitmap-too-large

Also available as: JSON · Markdown · 中文
85%Fix Rate
88%Confidence
1Evidence
2023-05-12First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
Android 12 (API 31) active
Android 13 (API 33) active
Android 14 (API 34) active
Glide 4.15 active
Coil 2.4.0 active

Root Cause

App tries to load a large bitmap (e.g., from camera or network) into memory without downscaling, exceeding the per-app heap limit.

generic

中文

应用尝试将大位图(例如,来自相机或网络)加载到内存而不进行缩放,超过了每个应用的堆限制。

Official Documentation

https://developer.android.com/topic/performance/graphics/load-bitmap

Workarounds

  1. 90% success Use BitmapFactory.Options to downsample the image: BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; // reduces size by factor of 4 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options);
    Use BitmapFactory.Options to downsample the image: BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; // reduces size by factor of 4 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options);
  2. 95% success Use an image loading library like Glide or Coil that handles downsampling and caching automatically: Glide.with(context).load(url).override(800, 600).into(imageView);
    Use an image loading library like Glide or Coil that handles downsampling and caching automatically: Glide.with(context).load(url).override(800, 600).into(imageView);
  3. 85% success If loading from camera, use getBitmap() with a reduced max dimension: Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); where options.inJustDecodeBounds = true is used first to calculate the sample size.
    If loading from camera, use getBitmap() with a reduced max dimension: Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); where options.inJustDecodeBounds = true is used first to calculate the sample size.

中文步骤

  1. Use BitmapFactory.Options to downsample the image: BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; // reduces size by factor of 4 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large_image, options);
  2. Use an image loading library like Glide or Coil that handles downsampling and caching automatically: Glide.with(context).load(url).override(800, 600).into(imageView);
  3. If loading from camera, use getBitmap() with a reduced max dimension: Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options); where options.inJustDecodeBounds = true is used first to calculate the sample size.

Dead Ends

Common approaches that don't work:

  1. 80% fail

    Increasing the heap size via android:largeHeap="true" in the manifest is not a reliable fix because the system may still kill the app, and it only provides a larger limit, not unlimited memory.

  2. 90% fail

    Using BitmapFactory.decodeResource() without any options loads the full-resolution bitmap, which will still cause OOM for large images.

  3. 85% fail

    Calling System.gc() before loading an image does not guarantee that enough memory will be freed, and the garbage collector may not run immediately.