Typical ANR in Android Vitals

Amit Gupta
4 min readDec 12, 2020

--

executing service com.yourapppackagename/androidx.work.impl.background.systemjob.SystemJobService

at java.lang.Object.wait! (Native method)
at java.lang.Thread.parkFor$ (Thread.java:1220)
at sun.misc.Unsafe.park (Unsafe.java:299)
at java.util.concurrent.locks.LockSupport.park (LockSupport.java:158)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt (AbstractQueuedSynchronizer.java:810)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly (AbstractQueuedSynchronizer.java:970)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly (AbstractQueuedSynchronizer.java:1278)
at java.util.concurrent.CountDownLatch.await (CountDownLatch.java:203)
at android.app.SharedPreferencesImpl$EditorImpl$1.run (SharedPreferencesImpl.java:366)
at android.app.QueuedWork.waitToFinish (QueuedWork.java:88)
at android.app.ActivityThread.handleStopService (ActivityThread.java:4165)
at android.app.ActivityThread.access$2500 (ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1929)
at android.os.Handler.dispatchMessage (Handler.java:102)
at android.os.Looper.loop (Looper.java:148)
at android.app.ActivityThread.main (ActivityThread.java:7325)
at java.lang.reflect.Method.invoke! (Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)

Have you faced the above ANR in your android App which does not give clue where we should check it and how can we fix it?

Working with one Project , I faced this kind of ANR suddenly from previous 2 builds , I did profiling and found so many threads are spanning in our app during launch time and I try to check WorkManager Services so many times if these services are creating deadlock anywhere while accessing Room Database or while doing concurrent operations But was not able to reach to some conclusion for some time And once i did Google for it there is no concrete solution why these are occurring since Logs does not give class file logs which are written for your project.

Now Problem became more interesting to me as I was going in more depth of it. Then I focused on this line:

java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly (AbstractQueuedSynchronizer.java:1278)
at java.util.concurrent.CountDownLatch.await (CountDownLatch.java:203)
at android.app.SharedPreferencesImpl$EditorImpl$1.run (SharedPreferencesImpl.java:366)

Is there something related to SharedPreference which is causing these ANRs? I do start researching and yes I was right , the main culprit was the SharedPreferences extensive and frequent usage in the application, This was very strange for me for the first time since I never see the side effect of using SharedPreferences in the app , It may be because it was not frequently used before in the app.

I will just give some brief what was causing problem in respect of our Paytm Application and will keep the solution very generic so that it can help others to solve their ANRs if the reason is same.

We fetch Backend Api urls and our localisation Strings at run time in every 8 hrs in the app and save them in cache using Shared preferences so that Least recently used data in previous session can be fetched at app launch 2nd time onwards. Once users will click on more pages, then more urls and more localised strings will be fetched from server and saved in Shared Preferences for caching purpose for the next session so that it is available to app launch.

I think now you are understood how frequently we were using Shared Preferences edit operations and we have used apply() instead of commit() while saving data in cache for Asynchronous operation. It seems there is no problem in it since it is asynchronous operation and will not give any problem.

Now the problem was started . I am giving some key points about Shared Preferences operations first then you will automatically get the answer.

1.) It may be because of you are running SharedPreferences apply() method very frequently which are spanning so many threads and all threads are trying to write to the same shared preference file which are queued and hence it consumes all threads or cores of your device for processing which may be causing ANR on low configuration devices.

2.) If you are using commit() for the same Shared Preferences for which you have called apply() previously then it will be blocking call on main thread for all previous apply() asynchronous operations for the same SharedPreference which may cause ANR on main thread. Since using apply() method you are queuing all edit operations on the same file which may take time to finish.

3.) May be some big data is saved in Shared Preference because of which other commit()/apply() are placed in queue and waiting for their turn to write to the I/O file and and hence it consumes all threads or cores of your device for processing which may be causing ANR on low configuration devices.

4.) Once Frequent apply() are used it consumes more RAM memory to save SharedPreferences Data in temporary storage before executing Asynchronous operation to save it in I/O file. So for Low End Devices , no further RAM is available for main thread operation which increase memory pressure on app and cause ANRs.

So the main problem was frequent edit operation on SharedPreferences which were blocking our main thread for some time and it was causing ANR. Our App ANR was drastically reduced after fixing it and also app startup time was improved almost by 10%. To fix it we now using Room database to keep the LRU data and it worked smoothly.

I hope it will be helpful for someone who is facing the ANR problem without no clue. Please do clap if you liked it.

--

--

Amit Gupta
Amit Gupta

Responses (1)