mapbox / mapbox-gl-native

Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL
https://mapbox.com/mobile
Other
4.35k stars 1.33k forks source link

Android Bitmap memory leak leads to OutOfMemoryError #16579

Closed iwo closed 2 years ago

iwo commented 3 years ago

Platform:

Android

Especially affects older Android versions:

59% Android 6
23% Android 7
17% Android 5

Mapbox SDK version:

9.5.1

Problem description

Each initialization of map leaks one Bitmap that contains sprite (icons). If user navigates a lot between app screen so that new map activities are created the leaks accumulate which eventually leads to the OutOfMemoryError or process kill.

Screenshot 2021-01-14 at 10 59 01

In Crashlytics we see a lot of reports like this:

Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 35346444 byte allocation with 16776472 free bytes and 25MB until OOM
       at dalvik.system.VMRuntime.newNonMovableArray(VMRuntime.java)
       at android.graphics.BitmapFactory.nativeDecodeByteArray(BitmapFactory.java)
       at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:613)
       at android.graphics.BitmapFactory.decodeByteArray(BitmapFactory.java:636)

This call appears to be made from native code here https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/bitmap_factory.cpp

Steps to trigger behavior

  1. Setup Android 6 (API 23) emulator with smaller VM heap (e.g. 128MB) - small heaps size is not strictly required but it makes the crash happen earlier
  2. Install MapboxAndroidDemo app
  3. Open "A simple map view" example
  4. Wait until the map loads
  5. Close the view - return to examples list
  6. Repeat from step 3 multiple times

Expected behaviour

Memory usage doesn't grow on subsequent opening "A simple map view". The app doesn't crash after opening the screen many times.

Actual behavior

On each opening of "A simple map view" the memory usage grows by ~10MB. After repeating the open/close action multiple times the app gets killed.

Suggested fixes

Bitmap should be cached and reused to avoid overhead of large allocations. See https://developer.android.com/topic/performance/graphics/manage-memory Alternatively [Bitmap.recycle()](https://developer.android.com/reference/android/graphics/Bitmap?hl=en#recycle()) may be called explicitly to clear the resources.

iwo commented 2 years ago

I can't reproduce this issue any more.