Android - मैं एक ANR की जांच कैसे करूँ?


153

क्या यह पता लगाने का कोई तरीका है कि मेरे ऐप ने एक ANR (एप्लिकेशन रिस्पॉन्सिंग नहीं) फेंक दिया है। मैंने / डेटा में traces.txt फ़ाइल पर एक नज़र डाली और मुझे अपने आवेदन के लिए एक निशान दिखाई दिया। यह मैं ट्रेस में देख रहा हूँ।

DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
  | group="main" sCount=1 dsCount=0 s=0 obj=0x400143a8
  | sysTid=691 nice=0 sched=0/0 handle=-1091117924
  at java.lang.Object.wait(Native Method)
  - waiting on <0x1cd570> (a android.os.MessageQueue)
  at java.lang.Object.wait(Object.java:195)
  at android.os.MessageQueue.next(MessageQueue.java:144)
  at android.os.Looper.loop(Looper.java:110)
  at android.app.ActivityThread.main(ActivityThread.java:3742)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:515)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)
  at dalvik.system.NativeStart.main(Native Method)

"Binder Thread #3" prio=5 tid=15 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x434e7758
  | sysTid=734 nice=0 sched=0/0 handle=1733632
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #2" prio=5 tid=13 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433af808
  | sysTid=696 nice=0 sched=0/0 handle=1369840
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=11 NATIVE
  | group="main" sCount=1 dsCount=0 s=0 obj=0x433aca10
  | sysTid=695 nice=0 sched=0/0 handle=1367448
  at dalvik.system.NativeStart.run(Native Method)

"JDWP" daemon prio=5 tid=9 VMWAIT
  | group="system" sCount=1 dsCount=0 s=0 obj=0x433ac2a0
  | sysTid=694 nice=0 sched=0/0 handle=1367136
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
  | group="system" sCount=0 dsCount=0 s=0 obj=0x433ac1e8
  | sysTid=693 nice=0 sched=0/0 handle=1366712
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 s=0 obj=0x4253ef88
  | sysTid=692 nice=0 sched=0/0 handle=1366472
  at dalvik.system.NativeStart.run(Native Method)

----- end 691 -----

मैं कैसे पता लगा सकता हूं कि समस्या कहां है? ट्रेस में विधियां सभी एसडीके विधियां हैं।

धन्यवाद।


2
इस तरह की एक रिपोर्ट मेरे पास भी है android.os.MessageQueue.nativePollOnce(Native Method)। क्या मैं इसे सुरक्षित रूप से अनदेखा कर सकता हूं?
आरडीएस

जवाबों:


124

एक एएनआर तब होता है जब कुछ लंबा ऑपरेशन "मुख्य" धागे में होता है। यह ईवेंट लूप थ्रेड है, और यदि यह व्यस्त है, तो Android एप्लिकेशन में किसी भी GUI इवेंट को संसाधित नहीं कर सकता है, और इस प्रकार ANR संवाद फेंकता है।

अब, आपके द्वारा पोस्ट किए गए ट्रेस में, मुख्य धागा ठीक काम कर रहा है, कोई समस्या नहीं है। यह MessageQueue में निष्क्रिय है, एक और संदेश के आने का इंतजार कर रहा है। आपके मामले में ANR संभवतः एक लंबा ऑपरेशन था, बजाय इसके कि थ्रेड को स्थायी रूप से अवरुद्ध कर दिया जाए, इसलिए ऑपरेशन समाप्त होने के बाद ईवेंट थ्रेड पुनर्प्राप्त हो गया, और आपका ट्रेस समाप्त हो गया ANR के बाद।

यह पता लगाना कि एएनआर कहां होता है, अगर यह एक स्थायी ब्लॉक है (उदाहरण के लिए कुछ ताले प्राप्त करने में गतिरोध) तो आसान है, लेकिन अगर यह सिर्फ एक अस्थायी देरी है। सबसे पहले, अपने कोड पर जाएं और दिखावटी स्थानों और लंबे समय तक चलने वाले संचालन की तलाश करें। उदाहरणों में घटना थ्रेड के भीतर से सॉकेट्स, लॉक्स, थ्रेड स्लीप्स और अन्य ब्लॉकिंग ऑपरेशंस का उपयोग करना शामिल हो सकता है। आपको यह सुनिश्चित करना चाहिए कि ये सभी अलग-अलग थ्रेड में होते हैं। यदि समस्या कुछ भी नहीं है, तो DDMS का उपयोग करें और थ्रेड दृश्य को सक्षम करें। यह आपके एप्लिकेशन के सभी थ्रेड्स को आपके द्वारा दिखाए गए ट्रेस के समान दिखाता है। ANR को पुन: उत्पन्न करें, और एक ही समय में मुख्य धागे को ताज़ा करें। यह आपको एएनआर के समय ठीक होने वाले व्हाट्सएप दिखाना चाहिए


6
एकमात्र मुद्दा "ANR को पुन: उत्पन्न करना" :-) है। क्या आप बता सकते हैं कि स्टैक ट्रेस शो का मुख्य धागा 'आइडलिंग' कैसे है, यह बहुत अच्छा होगा।
ब्लंडेल

20
स्टैक ट्रेस दिखाता है कि मुख्य थ्रेड लूपर (संदेश लूप कार्यान्वयन) में है और Object.wait के माध्यम से समयबद्ध प्रतीक्षा कर रहा है। इसका मतलब यह है कि संदेश लूप में वर्तमान में प्रेषण करने के लिए कोई संदेश नहीं है, और नए संदेशों के आने का इंतजार कर रहा है। एक ANR तब होता है जब सिस्टम को पता चलता है कि संदेश लूप एक संदेश को संसाधित करने में बहुत समय खर्च कर रहा है, और अन्य संदेशों को संसाधित नहीं कर रहा है। कतार। यदि लूप संदेशों का इंतजार कर रहे हैं, तो जाहिर है कि ऐसा नहीं हो रहा है।
जल्द ही

3
@Soonil हाय क्या आप जानते हैं कि बाकी हिस्सों का मतलब क्या है जैसे कि बाइंडर थ्रेड 3, बाइंडर थ्रेड 2 JDWP दानव बेशकीमती 5. sCount, dsCount, obj, sysTid, नाइस शेड्यूल का क्या मतलब है। इसके पास VMWAIT, RUNNABLE, NATIVE
minhaz

1
मेरा ऐप एनडीके आधारित है, मैं उसी एएनआर को देखता हूं। इसके अलावा, मुख्य धागा ठीक है। मैंने डीडीएमएस की कोशिश की और अपने कार्यकर्ता धागे को ताज़ा कर दिया जब यह जमा देता है। दुर्भाग्य से सब मुझे मिलता है एक मूल पंक्ति NativeStart :: रन है। क्या DDMS थ्रेड दृश्य देशी NDK थ्रेड्स का निरीक्षण करने में भी सक्षम है? इसके अलावा: स्ट्रिक्टमोड को कुछ नहीं मिला।
ब्राम

6
आउटपुट की अच्छी व्याख्या के लिए elliotth.blogspot.com/2012/08/… देखें ।
जल्द ही

96

आप एपीआई स्तर 9 और इसके बाद के संस्करण में स्ट्रिक्टमोड को सक्षम कर सकते हैं।

स्ट्रिक्टमोड का उपयोग आमतौर पर एप्लिकेशन के मुख्य थ्रेड पर आकस्मिक डिस्क या नेटवर्क एक्सेस को पकड़ने के लिए किया जाता है, जहां यूआई संचालन प्राप्त होते हैं और एनिमेशन होते हैं। अपने एप्लिकेशन के मुख्य थ्रेड को उत्तरदायी रखकर, आप उपयोगकर्ताओं को दिखाए जाने वाले ANR संवादों को भी रोकते हैं

public void onCreate() {
    StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                           .detectAll()
                           .penaltyLog()
                           .penaltyDeath()
                           .build());
    super.onCreate();
}

उपयोग penaltyLog()करते हुए आप adb logcat का आउटपुट देख सकते हैं जब आप अपने एप्लिकेशन का उपयोग उल्लंघन करते हुए देखते हैं।


StrictMode को एक प्रकार से हल नहीं किया जा सकता है। क्या मुझे पहले आयात करने की कोई आवश्यकता है? CTRL + SHIFT + O दबाने से मदद नहीं मिलती है।
कच्ची

23
छोटे टिप - अगर (BuildConfig.DEBUG) का उपयोग करें ... उत्पादन में समावेश को रोकने के लिए
अमीर Uval

@ "आप उत्पादन में समावेश को रोकने के लिए" क्या मतलब है? !!
मुहम्मद रिफैट

2
@MuhammedRefaat यह किसी भी ANR को नहीं रोकता है। यह 5 सेकंड के बाद तुरंत ऐप को क्रैश कर देगा। उदाहरण के लिए, यदि आप डेटाबेस को मुख्य थ्रेड पर एक्सेस करते हैं और इसमें 2 सेकंड लगते हैं, तो आपको ANR नहीं मिलेगा, लेकिन StrictMode ऐप को क्रैश कर देगा। स्ट्रिक्टमोड आपके डिबगिंग चरण के लिए कड़ाई से है, उत्पादन नहीं।
आमिर उवल

1
@MuhammedRefaat ने आपके प्रश्न के लिए मेरा उत्तर जोड़ा।
अमीर उवाल

80

आप सोच रहे हैं कि UI थ्रेड किस कार्य को पकड़ता है। ट्रेस फ़ाइल आपको कार्य खोजने का संकेत देती है। आपको प्रत्येक थ्रेड की एक स्थिति की जांच करने की आवश्यकता है

धागे की अवस्था

  • चल रहा है - आवेदन कोड निष्पादित
  • नींद - थ्रेड। स्लीप ()
  • मॉनिटर - मॉनिटर लॉक प्राप्त करने की प्रतीक्षा कर रहा है
  • प्रतीक्षा करें - Object.wait में ()
  • देशी - निष्पादित देशी कोड
  • vmwait - VM संसाधन पर प्रतीक्षा कर रहा है
  • ज़ोंबी - धागा मरने की प्रक्रिया में है
  • init - धागा इनिशियलाइज़ हो रहा है (आपको यह नहीं देखना चाहिए)
  • शुरू - धागा शुरू होने वाला है (आपको यह भी नहीं देखना चाहिए)

SUSPENDED, MONITOR राज्य पर ध्यान दें। मॉनिटर स्थिति इंगित करती है कि किस थ्रेड की जांच की गई है और थ्रेड की SUSPENDED स्थिति संभवतः गतिरोध का मुख्य कारण है।

बुनियादी जांच कदम

  1. "लॉक करने के लिए प्रतीक्षा करें" ढूंढें
    • आप मॉनिटर स्टेट "बाइंडर थ्रेड # 15" प्रियो = 5 tid = 75 MONITOR पा सकते हैं
    • आप भाग्यशाली हैं यदि "लॉक करने के लिए इंतजार" पाते हैं
    • उदाहरण: थ्रेडिड = 74 द्वारा आयोजित <0xblahblah> (एक com.foo.A) लॉक करने की प्रतीक्षा कर रहा है
  2. आप देख सकते हैं कि "tid = 74" अब एक कार्य करता है। तो tid = 74 पर जाएं
  3. tid = 74 शायद SUSPENDED राज्य! मुख्य कारण खोजें!

ट्रेस में हमेशा "लॉक का इंतजार" नहीं होता है। इस मामले में मुख्य कारण खोजना मुश्किल है।


1
अच्छी व्याख्या। अब मेरे लिए ANR लॉग को समझना आसान हो गया है। लेकिन मुझे अभी भी समझने की समस्या है क्योंकि चरण 1 में मैं आसानी से थ्रेड आईडी खोजने में सक्षम हूं, लेकिन जब चरण 2 में, मैं जाने की कोशिश कर रहा हूं कि यह कहां है, राज्य की जांच करने के लिए, मैं इसे नहीं ढूंढ सकता हूं । किसी भी विचार कैसे इसके साथ आगे बढ़ना है?
THZ

1
मेरे - waiting to lock an unknown objectअंदर है "HeapTaskDaemon" daemon prio=5 tid=8 Blocked । इसका क्या मतलब है कि कोई मदद कर सकता है?
हिलाल

13

मैं पिछले कुछ महीनों से एंड्रॉइड सीख रहा हूं, इसलिए मैं एक विशेषज्ञ से बहुत दूर हूं, लेकिन मैं वास्तव में ANR पर प्रलेखन से निराश हूं।

अधिकांश सलाह उन्हें टालने या अपने कोड के माध्यम से आँख बंद करके उन्हें ठीक करने की ओर लगती है, जो बहुत अच्छा है, लेकिन मुझे ट्रेस का विश्लेषण करने पर कुछ भी नहीं मिला।

वहाँ तीन चीजें हैं जो आप वास्तव में ANR लॉग के साथ देखने की जरूरत है।

1) डेडलॉक: जब कोई धागा WAIT राज्य में होता है, तो आप विवरणों के माध्यम से देख सकते हैं कि यह "जर्जर =" कौन है। ज्यादातर समय, यह अपने आप से आयोजित किया जाएगा, लेकिन अगर यह किसी अन्य धागे द्वारा आयोजित किया जाता है, तो यह खतरे का संकेत है। उस धागे को देखें और देखें कि यह किसके पास है। आपको एक लूप मिल सकता है, जो स्पष्ट संकेत है कि कुछ गलत हो गया है। यह बहुत दुर्लभ है, लेकिन यह पहला बिंदु है क्योंकि जब ऐसा होता है, तो यह एक बुरा सपना होता है

2) मुख्य धागा प्रतीक्षा कर रहा है: यदि आपका मुख्य धागा WAIT राज्य में है, तो जांचें कि क्या यह किसी अन्य धागे द्वारा रखा गया है। ऐसा नहीं होना चाहिए, क्योंकि आपके UI थ्रेड को बैकग्राउंड थ्रेड द्वारा आयोजित नहीं किया जाना चाहिए।

इन दोनों परिदृश्यों का अर्थ है कि आपको अपने कोड को महत्वपूर्ण रूप से पुनः बनाने की आवश्यकता है।

3) मुख्य धागे पर भारी ऑपरेशन: यह ANR का सबसे आम कारण है, लेकिन कभी-कभी इसे खोजने और ठीक करने के लिए कठिन में से एक है। मुख्य सूत्र विवरण देखें। स्टैक ट्रेस को नीचे स्क्रॉल करें और जब तक आप उन कक्षाओं को न देखें जिन्हें आप पहचानते हैं (अपने ऐप से)। ट्रेस में विधियों को देखें और पता करें कि क्या आप इन स्थानों पर नेटवर्क कॉल, डीबी कॉल आदि कर रहे हैं।

अंत में, और मैं बेशर्मी से अपना कोड प्लग करने के लिए माफी माँगता हूँ, आप https://github.com/HarshEvilGeek/Android-Log-Analyzer पर लिखे अजगर लॉग विश्लेषक का उपयोग कर सकते हैं। यह आपकी लॉग फ़ाइलों के माध्यम से जाएगा, ANR फ़ाइलें खोलें, खोजें गतिरोध, मुख्य थ्रेड्स की प्रतीक्षा करें, अपने एजेंट लॉग में अनियोजित अपवादों को ढूंढें और स्क्रीन पर सभी को अपेक्षाकृत आसान तरीके से पढ़ने के लिए प्रिंट करें। ReadMe फ़ाइल पढ़ें (जो मैं जोड़ने वाला हूं) यह जानने के लिए कि इसका उपयोग कैसे करना है। यह मुझे पिछले सप्ताह में एक टन की मदद की है!


4

जब भी आप समय के मुद्दों का विश्लेषण कर रहे हैं, डिबगिंग अक्सर मदद नहीं करता है, क्योंकि एक ब्रेकपॉइंट पर ऐप को फ्रीज करने से समस्या दूर हो जाएगी।

आपका सबसे अच्छा दांव ऐप के विभिन्न थ्रेड्स और कॉलबैक में लॉगिंग कॉल (Log.XXX ()) के बहुत सारे सम्मिलित करना है और देखें कि देरी कहाँ है। यदि आपको स्टैकट्रेस की आवश्यकता है, तो एक नया अपवाद बनाएं (बस एक पल में) और इसे लॉग इन करें।


2
यदि आपको स्टैकट्रेस की आवश्यकता है, तो एक नया अपवाद बनाने की सलाह के लिए धन्यवाद। डिबगिंग के समय यह बहुत मददगार होता है :)
kuchi

3

क्या ट्रिगर ANR?

आमतौर पर, सिस्टम एक ANR प्रदर्शित करता है यदि कोई एप्लिकेशन उपयोगकर्ता इनपुट पर प्रतिक्रिया नहीं दे सकता है।

किसी भी स्थिति में जिसमें आपका ऐप एक संभावित लंबा ऑपरेशन करता है, आपको यूआई थ्रेड पर काम नहीं करना चाहिए, बल्कि एक वर्कर थ्रेड बनाएं और वहां अधिकांश काम करें। यह UI थ्रेड (जो उपयोगकर्ता इंटरफ़ेस इवेंट लूप को चलाता है) को चालू रखता है और सिस्टम को यह निष्कर्ष निकालने से रोकता है कि आपका कोड जम गया है।

एएनआर से कैसे बचें

एंड्रॉइड एप्लिकेशन सामान्य रूप से "यूआई थ्रेड" या "मुख्य थ्रेड") डिफ़ॉल्ट रूप से एक ही थ्रेड पर पूरी तरह से चलते हैं। इसका मतलब यह है कि आपका आवेदन यूआई थ्रेड में कुछ भी कर रहा है जिसे पूरा करने में एक लंबा समय लग सकता है क्योंकि एएनआर संवाद को ट्रिगर किया जा सकता है क्योंकि आपका आवेदन खुद को इनपुट ईवेंट या इरादे प्रसारण को संभालने का मौका नहीं दे रहा है।

इसलिए, यूआई थ्रेड में चलने वाली कोई भी विधि उस थ्रेड पर जितना संभव हो उतना कम काम करना चाहिए। विशेष रूप से, गतिविधियों को ऑन-क्रेट () और ऑनस्क्यूम () जैसे प्रमुख जीवन-चक्र विधियों में स्थापित करने के लिए जितना संभव हो उतना कम करना चाहिए। संभावित रूप से लंबे समय तक चलने वाले संचालन जैसे कि नेटवर्क या डेटाबेस संचालन, या कम्प्यूटेशनल रूप से महंगी गणना जैसे बिटमैप को एक कार्यकर्ता थ्रेड में (या डेटाबेस ऑपरेशन के मामले में, अतुल्यकालिक अनुरोध के माध्यम से) किया जाना चाहिए।

कोड: AsyncTask क्लास के साथ वर्कर थ्रेड

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    // Do the long-running work in here
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return totalSize;
    }

    // This is called each time you call publishProgress()
    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    // This is called when doInBackground() is finished
    protected void onPostExecute(Long result) {
        showNotification("Downloaded " + result + " bytes");
    }
}

कोड: एक्सक्यूट वर्कर थ्रेड

इस वर्कर थ्रेड को निष्पादित करने के लिए, बस एक उदाहरण बनाएं और एग्जीक्यूट कॉल करें ():

new DownloadFilesTask().execute(url1, url2, url3);

स्रोत

http://developer.android.com/training/articles/perf-anr.html


1

एएनआर के साथ मेरा मुद्दा, बहुत काम के बाद मुझे पता चला कि एक थ्रेड एक ऐसे संसाधन को बुला रहा था जो लेआउट में मौजूद नहीं था, एक अपवाद को वापस करने के बजाय, मुझे एएनआर मिला ...


यह बेहद अजीब है
नीलाभ


0

@Horyun ली के उत्तर पर बुनियादी, मैंने ANR की जांच करने में मदद करने के लिए एक छोटी सी अजगर स्क्रिप्ट लिखीtraces.txt

graphvizयदि आप grapvhvizअपने सिस्टम पर स्थापित हैं, तो ANR ग्राफिक्स के रूप में आउटपुट करेगा ।

$ ./anr.py --format png ./traces.txt

अगर फ़ाइल में ANR पाए जाते हैं तो नीचे png आउटपुट की तरह होगा traces.txt। यह अधिक सहज है।

यहाँ छवि विवरण दर्ज करें

traces.txtऊपर उपयोग की गई नमूना फ़ाइल यहाँ से प्राप्त हुई थी ।


0

एएनआर-वॉचडॉग पुस्तकालय का उपयोग करने पर विचार करें और एएनआर स्टैक के निशान को उच्च स्तर पर ट्रैक करें। फिर आप उन्हें अपनी क्रैश रिपोर्टिंग लाइब्रेरी में भेज सकते हैं। मैं उपयोग करने की सलाह देता हूंsetReportMainThreadOnly() इस परिदृश्य में । आप या तो ऐप को फ्रीज़ पॉइंट के एक गैर-घातक अपवाद को फेंक सकते हैं, या एएनआर होने पर ऐप बल छोड़ सकते हैं।

ध्यान दें कि आपके Google Play डेवलपर कंसोल पर भेजे गए मानक ANR रिपोर्ट अक्सर सटीक समस्या को इंगित करने के लिए पर्याप्त नहीं होते हैं। इसलिए तीसरे पक्ष के पुस्तकालय की आवश्यकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.