ऐप्लिकेशन काम नहीं कर रहा है (एएनआर) वाली गड़बड़ियां तब ट्रिगर होती हैं, जब ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड पांच सेकंड से ज़्यादा समय तक काम नहीं करता. Android दस्तावेज़ में, एएनआर और एएनआर का पता लगाने के बारे में ज़्यादा जानकारी पढ़ी जा सकती है.
इसके अलावा, Crashlytics की मदद से, समस्या वाले थ्रेड का पता लगाया जा सकता है. हम ANR वाली गड़बड़ियों का विश्लेषण करते हैं. इसके बाद, DevOps और यूज़र ऐक्टिविटी > Crashlytics डैशबोर्ड में, हम लागू होने वाले थ्रेड को टैग करते हैं, ताकि ANR वाली गड़बड़ी को डीबग करने के बारे में हिंट मिल सके.
इस पेज पर मौजूद सेक्शन में, हर एएनआर टैग का मतलब बताया गया है. साथ ही, उस टैग के साथ एएनआर का उदाहरण दिखाया गया है. इसके अलावा, एएनआर को डीबग करने का सुझाया गया तरीका भी बताया गया है.
Triggered ANR
जिस थ्रेड को लंबे समय तक ब्लॉक किया गया था और जिसकी वजह से एएनआर ट्रिगर हुआ था उसे इस Triggered ANR टैग के साथ एनोटेट किया जाता है.
समस्या वाली थ्रेड, ऐप्लिकेशन की मुख्य थ्रेड हो सकती है या ऐसी कोई भी थ्रेड हो सकती है जो काम नहीं कर रही है. हालांकि, यह ज़रूरी नहीं है कि Triggered ANR के तौर पर टैग किया गया थ्रेड ही एएनआर की असल वजह हो. इन एएनआर को डीबग करने और ठीक करने के लिए अहम जानकारी देने के मकसद से,
Crashlytics उन सभी थ्रेड को भी टैग करता है जो एएनआर में शामिल हैं. इस पेज के अगले सेक्शन में, उन अन्य टैग के बारे में जानें जिन्हें किसी थ्रेड पर लागू किया जा सकता है.
Deadlocked
अगर कोई थ्रेड किसी ऐसे डेडलॉक में शामिल है जिसकी वजह से एएनआर की गड़बड़ी हुई है, तो उसे इस Deadlocked टैग के साथ एनोटेट किया जाता है.
डेडलॉक तब होता है, जब कोई थ्रेड इंतज़ार की स्थिति में चला जाता है. ऐसा इसलिए होता है, क्योंकि ज़रूरी संसाधन किसी दूसरे थ्रेड के पास होता है. यह थ्रेड भी पहले थ्रेड के पास मौजूद संसाधन का इंतज़ार कर रहा होता है. अगर ऐप्लिकेशन का मुख्य थ्रेड इस स्थिति में है, तो ANR की गड़बड़ियां होने की संभावना है.
उदाहरण देखें
यहां डेडलॉक में शामिल दो थ्रेड दिए गए हैं:
main (unknown): tid=1 systid=1568
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.getPackage(PackageManagerService.java:22701)
com.android.server.pm.PackageManagerService$PackageManagerInternalImpl.filterOnlySystemPackages(PackageManagerService.java:22787)
...
com.android.server.SystemServer.main(SystemServer.java:368)
java.lang.reflect.Method.invoke(Native method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:517)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
ActivityManager (unknown): tid=21 systid=1902
com.android.server.pm.PackageManagerService.getPackageSetting(PackageManagerService.java:23618)
com.android.server.pm.PackageManagerService.getPackageUid(PackageManagerService.java:4542)
...
android.os.Handler.handleCallback(Handler.java:907)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:216)
android.os.HandlerThread.run(HandlerThread.java:67)
com.android.server.ServiceThread.run(ServiceThread.java:44)
सुझाव
डेड लॉक में शामिल थ्रेड देखें. साथ ही, उन थ्रेड से हासिल किए गए संसाधनों/लॉक की जांच करें. संभावित समाधानों के लिए, डेडलॉक और डेडलॉक को रोकने वाले एल्गोरिदम देखें.
IO Root blocking
धीमी I/O कार्रवाइयां करने वाले और Triggered ANR थ्रेड को ब्लॉक करने वाले किसी भी थ्रेड को IO Root blocking टैग के साथ एनोटेट किया जाता है. अगर Triggered ANR थ्रेड को अन्य थ्रेड ने ब्लॉक नहीं किया है, तो IO Root blocking थ्रेड भी एक Root blocking थ्रेड है.
उदाहरण देखें
Thread main(THREAD_STATE_TIMED_WAITING)
sun.misc.Unsafe.park( Unsafe.java:0 )
java.util.concurrent.locks.LockSupport.parkNanos( LockSupport.java:230 )
android.database.sqlite.SQLiteConnectionPool.waitForConnection( SQLiteConnectionPool.java:756 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
Thread main(THREAD_STATE_NATIVE_WAITING)
Syscall
art::ConditionVariable::WaitHoldingLocks(art::Thread*)
art::GoToRunnable(art::Thread*)
art::JniMethodEnd(unsigned int, art::Thread*)
libcore.io.Linux.fdatasync( Linux.java:0 )
libcore.io.ForwardingOs.fdatasync( ForwardingOs.java:105 )
...
java.io.RandomAccessFile.write( RandomAccessFile.java:559 )
...
android.app.ActivityThread.main( ActivityThread.java:8192 )
सुझाव
आम तौर पर, आपके ऐप्लिकेशन को मुख्य थ्रेड पर ज़्यादा समय लेने वाली I/O कार्रवाइयां नहीं करनी चाहिए. अगर मुख्य थ्रेड IO Root blocking है, तो स्ट्रिक्ट मोड का इस्तेमाल करके भी, मुख्य थ्रेड पर होने वाली किसी भी अनचाही I/O कार्रवाई की पहचान की जा सकती है.
Root blocking
Triggered ANR के तौर पर टैग किए गए थ्रेड को ब्लॉक करने वाले किसी भी थ्रेड को Root blocking टैग के साथ एनोटेट किया जाता है. अगर किसी थ्रेड को Root blocking और Triggered ANR, दोनों के तौर पर टैग किया गया है, तो ऐसी कोई दूसरी थ्रेड नहीं है जो उस थ्रेड को ब्लॉक करती हो.
अगर कोई Triggered ANR थ्रेड, अन्य थ्रेड के लिए इंतज़ार कर रहा था (शायद ट्रांज़िटिव तौर पर), तो वे Root blocking हैं. थ्रेड के एएनआर की असल वजह होने की कई वजहें हो सकती हैं.
उदाहरण देखें
यहां थ्रेड की स्थिति के आधार पर कुछ उदाहरण दिए गए हैं:
Thread main(THREAD_STATE_RUNNABLE)
android.os.Parcel.createTypedArray( Parcel.java:3086 )
android.content.pm.PackageInfo.<init>( PackageInfo.java:546 )
...
android.app.ActivityThread$H.handleMessage( ActivityThread.java:2166 )
android.os.Handler.dispatchMessage( Handler.java:106 )
android.os.Looper.loop( Looper.java:246 )
android.app.ActivityThread.main( ActivityThread.java:8633 )
Thread main(THREAD_STATE_BLOCKED)
DBHelper.runOnDB( DBHelper.java:97 )
DBHelper.runDb( DBHelper.java:125 )
...
java.lang.reflect.Method.invoke( Method.java:0 )
EventBus.invokeSubscriber( EventBus.java:510 )
postToSubscription( EventBus.java:437 )
...
android.os.Handler.handleCallback( Handler.java:938 )
android.os.Handler.dispatchMessage( Handler.java:99 )
android.os.Looper.loop( Looper.java:268 )
android.app.ActivityThread.main( ActivityThread.java:7904 )
सुझाव
मुख्य थ्रेड में, सीपीयू के ज़्यादा इस्तेमाल वाले काम को कम से कम करें. सीपीयू पर ज़्यादा लोड डालने वाले टास्क के लिए, वर्कर या बैकग्राउंड थ्रेड का इस्तेमाल करें.
मुख्य थ्रेड पर, डेटाबेस से लोड करने जैसे ज़्यादा I/O वाले काम को कम करें.
Unknown root cause
किसी थ्रेड को Unknown root cause टैग के साथ तब टैग किया जाता है, जब वह एएनआर को ट्रिगर करने वाला थ्रेड हो, लेकिन एएनआर होने पर प्रोसेस में कुछ न कर रहा हो. Crashlytics के पास, असल वजह का पता लगाने के लिए ज़रूरी जानकारी नहीं है. इस एएनआर के होने की कोई साफ़ वजह नहीं है.
उदाहरण देखें
Thread main(THREAD_STATE_NATIVE_WAITING) __epoll_pwait
android::Looper::pollInner(int)
android::Looper::pollOnce(int, int*, int*, void**)
android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)
android.os.MessageQueue.nativePollOnce( MessageQueue.java:0 )
android.os.MessageQueue.next( MessageQueue.java:335 )
android.os.Looper.loop( Looper.java:193 )
android.app.ActivityThread.main( ActivityThread.java:8019 )
सुझाव
ANR की गड़बड़ियों को रोकने के लिए, सामान्य सलाह का पालन करें. उदाहरण के लिए, अपने कोड में उन जगहों की पहचान करें जहां ऐप्लिकेशन का मुख्य थ्रेड, पांच सेकंड से ज़्यादा समय तक व्यस्त रह सकता है.
Waiting for binder call
बाइंडर कॉल का इंतज़ार करने वाले और Triggered ANR थ्रेड को ब्लॉक करने वाले किसी भी थ्रेड को Waiting for binder call टैग के साथ एनोटेट किया जाता है. अगर Triggered ANR थ्रेड को अन्य थ्रेड ने ब्लॉक नहीं किया है, तो Waiting for binder call थ्रेड भी एक Root blocking थ्रेड है.
उदाहरण देखें
Thread main(THREAD_STATE_NATIVE_WAITING)
syscall
android::IPCThreadState::talkWithDriver(bool)
android::IPCThreadState::waitForResponse(android::Parcel*, int*)
android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)
android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)
android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)
android.os.BinderProxy.transactNative( BinderProxy.java:0 )
android.os.BinderProxy.transact( BinderProxy.java:540 )
android.app.IActivityManager$Stub$Proxy.getContentProvider( IActivityManager.java:5945 )
android.app.ActivityThread.acquireProvider( ActivityThread.java:7138 )
android.app.ActivityThread$H.handleMessage( ActivityThread.java:1982 )
android.os.Handler.dispatchMessage( Handler.java:106 )
android.os.Looper.loop( Looper.java:236 )
android.app.ActivityThread.main( ActivityThread.java:8037 )
सुझाव
बाइंडर कॉल की इंतज़ार अवधि का अनुमान नहीं लगाया जा सकता. इसलिए, बाइंडर कॉल को I/O कार्रवाइयों की तरह ही ट्रीट करें. साथ ही, जब भी संभव हो, मुख्य थ्रेड पर बाइंडर कॉल करने से बचें. बाइंडर कॉल को ट्रिगर करने वाले कोड को बैकग्राउंड थ्रेड में ले जाएं. इसमें प्लैटफ़ॉर्म एपीआई कॉल भी शामिल हैं जिनकी वजह से बाइंडर लेन-देन होते हैं. इसके अलावा, अगर मुख्य थ्रेड से कॉल करना ज़रूरी है, तो नतीजों को कैश मेमोरी में सेव करें.