cordova-android: Crash Report: ConcurrentModificationException
Bug Report
Problem
We mentioned some Crash Reports from our App, build with cordova-android@8.1.0
. Crashlog:
java.util.ConcurrentModificationException: java.util.ConcurrentModificationException
java.util.LinkedHashMap$LinkedHashIterator.nextNode LinkedHashMap.java:775
java.util.LinkedHashMap$LinkedValueIterator.next LinkedHashMap.java:803
org.apache.cordova.PluginManager.onResume PluginManager.java:262
org.apache.cordova.CordovaWebViewImpl.handleResume CordovaWebViewImpl.java:452
org.apache.cordova.CordovaActivity.onResume CordovaActivity.java:277
android.app.Instrumentation.callActivityOnResume Instrumentation.java:1465
android.app.Activity.performResume Activity.java:8203
android.app.ActivityThread.performResumeActivity ActivityThread.java:4757
android.app.ActivityThread.handleResumeActivity ActivityThread.java:4810
android.app.servertransaction.ResumeActivityItem.execute ResumeActivityItem.java:52
android.app.servertransaction.TransactionExecutor.executeLifecycleState TransactionExecutor.java:190
android.app.servertransaction.TransactionExecutor.execute TransactionExecutor.java:105
android.app.ActivityThread$H.handleMessage ActivityThread.java:2373
android.os.Handler.dispatchMessage Handler.java:107
android.os.Looper.loop Looper.java:213
android.app.ActivityThread.main ActivityThread.java:8147
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:513
com.android.internal.os.ZygoteInit.main ZygoteInit.java:1101
and
java.util.ConcurrentModificationException: java.util.ConcurrentModificationException
java.util.LinkedHashMap$LinkedHashIterator.nextNode LinkedHashMap.java:760
java.util.LinkedHashMap$LinkedValueIterator.next LinkedHashMap.java:788
org.apache.cordova.PluginManager.onPause PluginManager.java:209
org.apache.cordova.CordovaWebViewImpl.handlePause CordovaWebViewImpl.java:435
org.apache.cordova.CordovaActivity.onPause CordovaActivity.java:245
android.app.Activity.performPause Activity.java:7663
android.app.Instrumentation.callActivityOnPause Instrumentation.java:1536
android.app.ActivityThread.performPauseActivityIfNeeded ActivityThread.java:4726
android.app.ActivityThread.performPauseActivity ActivityThread.java:4691
android.app.ActivityThread.handlePauseActivity ActivityThread.java:4626
android.app.servertransaction.PauseActivityItem.execute PauseActivityItem.java:45
android.app.servertransaction.TransactionExecutor.executeLifecycleState TransactionExecutor.java:145
android.app.servertransaction.TransactionExecutor.execute TransactionExecutor.java:70
android.app.ActivityThread$H.handleMessage ActivityThread.java:2199
android.os.Handler.dispatchMessage Handler.java:112
android.os.Looper.loop Looper.java:216
android.app.ActivityThread.main ActivityThread.java:7625
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:524
com.android.internal.os.ZygoteInit.main ZygoteInit.java:987
Environment, Platform, Device
From Crashlog this happens to a Mate 20 Pro with Android 9 and a Galaxy Note10+ with Android 10 too.
Maybe related Issue?
Please fix this 😊
Checklist
- I searched for existing GitHub issues
- I updated all Cordova tooling to most recent version
- I included all the necessary information above
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 37 (37 by maintainers)
Commits related to this issue
- Fix for #924 - Concurrent Modification Exception — committed to ebhsgit/cordova-android by ebhsgit 4 years ago
- Fix for #924 - Concurrent Modification Exception — committed to ebhsgit/cordova-android by ebhsgit 4 years ago
- Fix for #924 - Concurrent Modification Exception (#1091) Co-authored-by: 8bhsolutions <48874658+8bhsolutions@users.noreply.github.com> — committed to apache/cordova-android by ebhsgit 3 years ago
- Fix for #924 - Concurrent Modification Exception (#1091) Co-authored-by: 8bhsolutions <48874658+8bhsolutions@users.noreply.github.com> — committed to wedgberto/cordova-android by ebhsgit 3 years ago
I think all iterations of the plugin map needs to be synchronized, so logically I think I believe if you have a large number of plugins, you’ll see a bigger impact. I’ll test by installing all the apache plugins + maybe a few more and try to compare apps on cordova-android@8.1 vs the fork.
This is all just speculation, so we’ll see just how big of the impact is. The impact could be insignificant altogether as well, for all we know…
No problem 😄 so as far as we know, the
synchronizedMap
wrapper is (hopefully) working. If you see a stack trace like that comes from 2.0.3+ then we still have a problem.I didn’t use PR #1073, so can’t comment whether it works or not. On my first attempt to fix the issue, I only changed the collection to
Collection.synchronizedMap
, and did not change thefor
loop toforeach
I can confirm that just changing to using the synchronizedMap does not fix the issue.
I will add that even if PR #1073 works, it will not fix all
ConcurrentModificationException
, because CME occurs on other methods as well. It’s just thatPostMessage
has the highest occurrence becausesplashscreen
plugin invokes it during app load, and that is when all other plugins are also loading at the same time.Are you saying the PR https://github.com/apache/cordova-android/pull/1073 did not address the issue for you?
Personally I don’t see a way around that if unrelated plugin code is causing conflicts. My motto is make the framework work, then find a way to optimise later if necessary. So I think that’s okay for now.
A PR would be appreciated. I was never able to reproduce this issue myself, and the combination of plugins in my production apps doesn’t appear to trigger this issue so I’m relying on your observations. If you can prepare a branch with those commits and create a PR, it will make it easy for @EinfachHans to try it on his own apps to see if it resolves the issue for him.
Ok… well that means I think every loop block needs to be inside a
synchronized
block… but honestly I haven’t found any resources that says that is necessary, as every example deals with using theIterator
class… so this is just another assumption… ThePluginManager
has a lot of methods that does iterations over it’s two maps.I’m not sure why
for...in
loops was chosen, I assumed for simplicity sake…Ok but know really. I got the same Crash for the Version with the Fork… 😕 This Time really^^
Huawei P30 Lite (Android 9)
Yeah i can see that the User with the Crash is using Version 2.0.3 which is the one we build today
So just to let you know: We release a new Version with the Fork included tomorrow 🎉
Currently we had two Versions released before. Within these we had for now over 35 Crash Reports (nearly daily).
To be clear he was just simply responding to my question haha…
If it only happened 30 times since you opened the issue, that’s approximately 1 occurrence per day… which means the chances of intentionally triggering the bug naturally will likely be extremely difficult.
I have a feeling that there are potential race conditions in the resume/pause lifecycles but we will likely need a controlled test case to prove it…
Or if you’re willing… I can branch off of 8.1 and implement
synchronizedMap
and you can fork my branch. We’ll see if the problem goes away. If it is a race condition, the java docs appears to suggest thatsynchronizedMap
should fix it by ensuring synchronised access to our plugin maps. I’m assuming this is at a performance cost though and I’m not sure how significant that would be…