flutter_background_geolocation icon indicating copy to clipboard operation
flutter_background_geolocation copied to clipboard

[Help Wanted]: `OutOfMemoryError`s and crashes occurring on some devices

Open frankvollebregt opened this issue 7 months ago • 2 comments

Required Reading

  • [x] Confirmed

Plugin Version

4.16.9

Mobile operating-system(s)

  • [ ] iOS
  • [x] Android

Device Manufacturer(s) and Model(s)

Samsung Galaxy A54 5G, Samsung Galaxy Tab A7 Lite, Samsung Galaxy M32 5G, Samsung Galaxy A32

Device operating-systems(s)

Android 13, 14

What do you require assistance about?

In the Google Play Console, some devices occassionally encounter java.lang.OutOfMemoryErrors, or crash with some native (segmentation fault-like) error. I'm unsure if this is even something that could be prevented by my own app or this package, hence a Help Wanted request and not a Bug report.

From the Google Play Console, I have the following devices:

  • Samsung Galaxy A54 5G @ Android 14: OutOfMemoryError
  • Samsung Galaxy Tab A7 Lite LTE @ Android 14: OutOfMemoryError
  • Samsung Galaxy M32 5G @ Android 13: native crash
  • Samsung Galaxy A32 @ Android 13: native crash

Are there any likely causes or possibilities to track down these issues? Unfortunately, these devices are our customers', so I'm unable to see or test them for myself. But maybe seeing the files in this package in the stack traces can help you point out where the issue originates from...

[Optional] Plugin Code and/or Config

bg.Config(
    debug: false,
    logLevel: bg.Config.LOG_LEVEL_INFO,
    stopOnTerminate: false,
    startOnBoot: false,
    batchSync: true,
    // With a location every 3 seconds,
    // this is expected to take about 4 minutes
    autoSync: true,
    autoSyncThreshold: 75,
    httpRootProperty: 'locations',
    maxDaysToPersist: 7,
    logMaxDays: 1,
    // When the apparent movement speed was over 144 km/h, discard the location
    speedJumpFilter: 40,
    // Disable the motion API, and never automatically pause the service
    disableMotionActivityUpdates: true,
    disableStopDetection: true,
    pausesLocationUpdatesAutomatically: false,

    authorization: bg.Authorization(accessToken: accessToken),
    url: endpoint,
    extras: {...},
    notification: ...,
    backgroundPermissionRationale: ...,
  )

[Optional] Relevant log output

Samsung Galaxy A54 5G @ Android 14:
Exception java.lang.OutOfMemoryError: Failed to allocate a 24 byte allocation with 53280 free bytes and 52KB until OOM, target footprint <US_SOCIAL_SECURITY_NUMBER>, growth limit <US_SOCIAL_SECURITY_NUMBER>; giving up on allocation because <1% of heap free after GC.
  at java.util.HashMap.newNode (HashMap.java:1907)
  at java.util.HashMap.putVal (HashMap.java:636)
  at java.util.HashMap.put (HashMap.java:617)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toMap (BackgroundGeolocationModule.java:1043)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toMap (BackgroundGeolocationModule.java:1041)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toMap (BackgroundGeolocationModule.java:1041)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toList (BackgroundGeolocationModule.java:1058)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.access$300 (BackgroundGeolocationModule.java)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule$11.onSuccess (BackgroundGeolocationModule.java:578)
  at com.transistorsoft.locationmanager.adapter.BackgroundGeolocation$v0$a.run (Unknown Source:8)
  at android.os.Handler.handleCallback (Handler.java:958)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:230)
  at android.os.Looper.loop (Looper.java:319)
  at android.app.ActivityThread.main (ActivityThread.java:8919)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:578)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1103)

Exception java.lang.OutOfMemoryError:
  at java.lang.StringFactory.newStringFromUtf8Bytes
  at java.lang.StringFactory.newStringFromBytes (StringFactory.java:94)
  at java.lang.StringFactory.newStringFromBytes (StringFactory.java:68)
  at java.lang.StringFactory.newStringFromBytes (StringFactory.java:44)
  at java.lang.Long.toString (Long.java:482)
  at org.json.JSONObject.numberToString (JSONObject.java:760)
  at org.json.JSONStringer.value (JSONStringer.java:258)
  at org.json.JSONObject.writeTo (JSONObject.java:734)
  at org.json.JSONStringer.value (JSONStringer.java:246)
  at org.json.JSONObject.writeTo (JSONObject.java:734)
  at org.json.JSONStringer.value (JSONStringer.java:246)
  at org.json.JSONArray.writeTo (JSONArray.java:616)
  at org.json.JSONStringer.value (JSONStringer.java:242)
  at org.json.JSONObject.writeTo (JSONObject.java:734)
  at org.json.JSONObject.toString (JSONObject.java:702)
  at com.transistorsoft.locationmanager.http.HttpService.a (SourceFile:11)
  at com.transistorsoft.locationmanager.http.HttpService.f (SourceFile:2)
  at com.transistorsoft.locationmanager.http.HttpService.e (SourceFile:1)
  at com.transistorsoft.locationmanager.http.HttpService$e.run (Unknown Source:22)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:644)
  at java.lang.Thread.run (Thread.java:1012)

---------------------------------------------------------------------------------------------------
Samsung Galaxy Tab A7 Lite LTE @ Android 14:
Exception java.lang.OutOfMemoryError:
  at java.util.LinkedHashMap.sequencedKeySet (LinkedHashMap.java:673)
  at java.util.LinkedHashMap.keySet (LinkedHashMap.java:658)
  at org.json.JSONObject.keys (JSONObject.java:664)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toMap (BackgroundGeolocationModule.java:1031)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toMap (BackgroundGeolocationModule.java:1041)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.toList (BackgroundGeolocationModule.java:1058)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule.access$300 (BackgroundGeolocationModule.java)
  at com.transistorsoft.flutter.backgroundgeolocation.BackgroundGeolocationModule$11.onSuccess (BackgroundGeolocationModule.java:578)
  at com.transistorsoft.locationmanager.adapter.BackgroundGeolocation$v0$a.run (Unknown Source:8)
  at android.os.Handler.handleCallback (Handler.java:958)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:230)
  at android.os.Looper.loop (Looper.java:319)
  at android.app.ActivityThread.main (ActivityThread.java:8919)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:578)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1103)

Exception java.lang.OutOfMemoryError:
  at java.util.Arrays.copyOf (Arrays.java:3585)
  at java.lang.AbstractStringBuilder.ensureCapacityInternal (AbstractStringBuilder.java:177)
  at java.lang.AbstractStringBuilder.append (AbstractStringBuilder.java:753)
  at java.lang.StringBuilder.append (StringBuilder.java:257)
  at org.json.JSONStringer.string (JSONStringer.java:354)
  at org.json.JSONStringer.key (JSONStringer.java:386)
  at org.json.JSONObject.writeTo (JSONObject.java:734)
  at org.json.JSONStringer.value (JSONStringer.java:246)
  at org.json.JSONObject.writeTo (JSONObject.java:734)
  at org.json.JSONStringer.value (JSONStringer.java:246)
  at org.json.JSONArray.writeTo (JSONArray.java:616)
  at org.json.JSONStringer.value (JSONStringer.java:242)
  at org.json.JSONObject.writeTo (JSONObject.java:734)
  at org.json.JSONObject.toString (JSONObject.java:702)
  at com.transistorsoft.locationmanager.http.HttpService.a (SourceFile:11)
  at com.transistorsoft.locationmanager.http.HttpService.f (SourceFile:2)
  at com.transistorsoft.locationmanager.http.HttpService.e (SourceFile:1)
  at com.transistorsoft.locationmanager.http.HttpService$e.run (Unknown Source:22)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:644)
  at java.lang.Thread.run (Thread.java:1012)

---------------------------------------------------------------------------------------------------
Samsung Galaxy M32 5G @ Android 13:
SourceFile - com.transistorsoft.locationmanager.service.AbstractService.c
  #00  pc 0x00000000004fc1e0  /apex/com.android.art/lib64/libart.so (art::DumpNativeStack+108)
  #01  pc 0x00000000004fe898  /apex/com.android.art/lib64/libart.so (art::Thread::DumpStack const+376)
  #02  pc 0x000000000050068c  /apex/com.android.art/lib64/libart.so (art::DumpCheckpoint::Run+216)
  #03  pc 0x000000000022c2b0  /apex/com.android.art/lib64/libart.so (art::Thread::RunCheckpointFunction+144)
  #04  pc 0x0000000000993c24  /apex/com.android.art/lib64/libart.so (artTestSuspendFromCode+152)
  #05  pc 0x000000000037e99c  /apex/com.android.art/lib64/libart.so (art_quick_test_suspend+156)
  at android.os.Parcel.nativeWriteString16 (Native method)
  at android.os.Parcel.writeString16NoHelper (Parcel.java:1146)
  at android.os.Parcel$ReadWriteHelper.writeString16 (Parcel.java:486)
  at android.os.Parcel.writeString16 (Parcel.java:1125)
  at android.os.Parcel.writeString (Parcel.java:1115)
  at android.os.Parcel.writeArrayMapInternal (Parcel.java:1298)
  at android.os.BaseBundle.writeToParcelInner (BaseBundle.java:1802)
  at android.os.Bundle.writeToParcel (Bundle.java:1362)
  at android.os.Parcel.writeBundle (Parcel.java:1368)
  at android.app.Notification.writeToParcelImpl (Notification.java:3223)
  at android.app.Notification.writeToParcel (Notification.java:3099)
  at android.os.Parcel.writeTypedObject (Parcel.java:2191)
  at android.app.IActivityManager$Stub$Proxy.setServiceForeground (IActivityManager.java:6987)
  at android.app.Service.startForeground (Service.java:743)
  at com.transistorsoft.locationmanager.service.AbstractService.c (SourceFile:1)
  at com.transistorsoft.locationmanager.service.AbstractService.a (SourceFile:8)
  at com.transistorsoft.locationmanager.service.TrackingService.onStartCommand (unavailable:1)
  at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:5243)
  at android.app.ActivityThread.-$$Nest$mhandleServiceArgs (unavailable)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2447)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8762)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)

---------------------------------------------------------------------------------------------------
Samsung Galaxy A32 @ Android 13:
SourceFile - com.transistorsoft.locationmanager.service.AbstractService.c
  #00  pc 0x00000000006aa9a8  /apex/com.android.art/lib64/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, BacktraceMap*, char const*, art::ArtMethod*, void*, bool)+128)
  #01  pc 0x0000000000712b44  /apex/com.android.art/lib64/libart.so (art::Thread::DumpStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, bool, BacktraceMap*, bool) const+236)
  #02  pc 0x0000000000721d90  /apex/com.android.art/lib64/libart.so (art::DumpCheckpoint::Run(art::Thread*)+208)
  #03  pc 0x0000000000424f94  /apex/com.android.art/lib64/libart.so (art::Thread::RunCheckpointFunction()+140)
  #04  pc 0x000000000077f90c  /apex/com.android.art/lib64/libart.so (artTestSuspendFromCode+48)
  #05  pc 0x000000000046113c  /apex/com.android.art/lib64/libart.so (art_quick_test_suspend+156)
  at android.os.Parcel.nativeWriteString8 (Native method)
  at android.os.Parcel.writeString8NoHelper (Parcel.java:1141)
  at android.os.Parcel$ReadWriteHelper.writeString8 (Parcel.java:482)
  at android.os.Parcel.writeString8 (Parcel.java:1120)
  at android.app.Notification.writeToParcelImpl (Notification.java:3211)
  at android.app.Notification.writeToParcel (Notification.java:3099)
  at android.os.Parcel.writeTypedObject (Parcel.java:2191)
  at android.app.IActivityManager$Stub$Proxy.setServiceForeground (IActivityManager.java:6987)
  at android.app.Service.startForeground (Service.java:743)
  at com.transistorsoft.locationmanager.service.AbstractService.c (SourceFile:1)
  at com.transistorsoft.locationmanager.service.AbstractService.a (SourceFile:8)
  at com.transistorsoft.locationmanager.service.TrackingService.onStartCommand (unavailable:1)
  at android.app.ActivityThread.handleServiceArgs (ActivityThread.java:5243)
  at android.app.ActivityThread.-$$Nest$mhandleServiceArgs (unavailable)
  at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2447)
  at android.os.Handler.dispatchMessage (Handler.java:106)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8762)
  at java.lang.reflect.Method.invoke (Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)

frankvollebregt avatar Jun 13 '25 14:06 frankvollebregt

batchSync: true, maxDaysToPersist: 7,

You should probably provide a maxBatchSize in order to prevent potentially 7 days of records being loaded into memory.

christocracy avatar Jun 13 '25 15:06 christocracy

Good call, I was under the impression the autoSyncTheshold would already make sure each request got that many records, but reading the docs again that's of course not true. I expect that in practice users log into the app at the start of their working day, and log back out near the end. When logging out, I call destroyLocations(), which should get rid of old records, but there might be a scenario I haven't kept in mind there (and aside from that, 7 days is definitely excessive for my actual use case).

I'll decrease the location persistence and add the maxBatchSize to see if it helps for these devices.

Is there anything else that sticks out to you, that could have caused issues?

frankvollebregt avatar Jun 16 '25 06:06 frankvollebregt

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar Jul 17 '25 02:07 github-actions[bot]

This issue was closed because it has been inactive for 14 days since being marked as stale.

github-actions[bot] avatar Jul 31 '25 02:07 github-actions[bot]