Crashlytics डैशबोर्ड में, ANR टैग के आधार पर अपने Android ऐप्लिकेशन को डीबग करने का तरीका

'ऐप्लिकेशन काम नहीं कर रहा है' (ANR) वाली गड़बड़ियां तब ट्रिगर होती हैं, जब ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड पांच सेकंड से ज़्यादा समय तक काम नहीं कर रहा हो. Android दस्तावेज़ में, एएनआर और एएनआर का पता लगाने के बारे में ज़्यादा पढ़ा जा सकता है.

इसके अलावा, Crashlytics की मदद से, समस्या वाली खास थ्रेड की पहचान की जा सकती है. हम ANR का विश्लेषण करते हैं. इसके बाद, Crashlytics डैशबोर्ड में, हम लागू होने वाली थ्रेड को टैग करते हैं, ताकि ANR को डीबग करने का तरीका बताया जा सके.

इस पेज पर दिए गए सेक्शन में बताया गया है कि हर एएनआर टैग का क्या मतलब है. साथ ही, उस टैग के साथ एएनआर का एक उदाहरण दिखाया गया है. इसके अलावा, एएनआर को डीबग करने का सुझाया गया तरीका भी बताया गया है.

Triggered ANR

जिस थ्रेड को बहुत लंबे समय तक ब्लॉक किया गया था और जिसकी वजह से 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 हैं. किसी थ्रेड की वजह से ANR होने की कई वजहें हो सकती हैं.

थ्रेड की स्थिति के आधार पर, यहां कुछ उदाहरण दिए गए हैं:

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 टैग के साथ तब टैग किया जाता है, जब वह थ्रेड ANR को ट्रिगर करता है, लेकिन ANR होने के दौरान वह प्रोसेस में शामिल नहीं होता. Crashlytics में इस समस्या की मुख्य वजह का पता लगाने के लिए ज़रूरी जानकारी मौजूद नहीं है. इस ANR की कोई साफ़ वजह नहीं है.

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 से बचने के लिए, सामान्य सलाह अपनाएं. उदाहरण के लिए, अपने कोड में उन जगहों की पहचान करें जहां ऐप्लिकेशन का मुख्य थ्रेड पांच सेकंड से ज़्यादा समय तक व्यस्त हो सकता है.