ניפוי באגים באפליקציה ל-Android על סמך תגי ANR במרכז הבקרה של Crashlytics
קל לארגן דפים בעזרת אוספים
אפשר לשמור ולסווג תוכן על סמך ההעדפות שלך.
שגיאות מסוג 'האפליקציה לא מגיבה (ANR)' מופעלות כששרשור ממשק המשתמש של האפליקציה לא מגיב במשך יותר מ-5 שניות. מידע נוסף על מקרי ANR ועל אבחון שלהם זמין במסמכי Android.
בנוסף, Crashlytics יכול לעזור לזהות שרשורים ספציפיים שגורמים לבעיות. אנחנו מנתחים שגיאות ANR, ואז במרכז הבקרה של Crashlytics אנחנו מתייגים את השרשורים הרלוונטיים כדי לספק רמזים לגבי ניפוי הבאגים של שגיאות ה-ANR.
בקטעים הבאים בדף הזה מוסבר מה המשמעות של כל תג ANR, מוצגות דוגמאות ל-ANR עם התג הזה ומוצע פתרון מומלץ לניפוי הבאגים של ה-ANR.
Triggered ANR
Thread שנחסם למשך זמן ארוך מדי והפעיל את ה-ANR מסומן בתג Triggered ANR
.
השרשור הבעייתי יכול להיות השרשור הראשי של האפליקציה, או כל שרשור שלא מגיב. עם זאת, יכול להיות שהשרשור שתויג כ-Triggered ANR
הוא הסיבה האמיתית ל-ANR, ויכול להיות שלא. כדי לספק תובנות לניפוי באגים ולתיקון של מקרי ANR, Crashlytics מתייג גם את כל השרשורים האחרים שקשורים ל-ANR. בקטעים הבאים בדף הזה מוסבר על תגים אחרים שאפשר להוסיף לשרשור.
Deadlocked
כל השרשורים שנמצאו כמעורבים במבוי סתום שהוביל ל-ANR מסומנים בתג Deadlocked
.
מצב של deadlock מתרחש כש-thread נכנס למצב המתנה כי משאב נדרש מוחזק על ידי thread אחר, שגם הוא נמצא בהמתנה למשאב שמוחזק על ידי ה-thread הראשון. אם ה-thread הראשי של האפליקציה נמצא במצב הזה, סביר להניח שיוצגו שגיאות 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
כל thread שביצע פעולות קלט/פלט (I/O) איטיות וחסימה של ה-thread Triggered ANR
מתויג בתג IO Root blocking
. אם ה-thread Triggered ANR
לא נחסם על ידי threads אחרים, אז ה-thread IO Root blocking
הוא גם thread 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 )
המלצה
באופן כללי, האפליקציה לא צריכה לבצע פעולות קלט/פלט יקרות ב-thread הראשי. אם ה-thread הראשי הוא IO Root blocking
, אפשר גם להשתמש במצב קפדני כדי לזהות פעולות קלט/פלט לא מכוונות שמתבצעות ב-thread הראשי.
Root blocking
כל שרשור שחוסם את השרשור שתויג כ-Triggered ANR
יתויג בתג Root blocking
. אם שרשור מסומן בתגיות Root blocking
ו-Triggered ANR
, סימן שלא קיימים שרשורים אחרים שחוסמים את השרשור הזה.
אם יש threads של Triggered ANR
שנמצאים בהמתנה (אולי באופן טרנזיטיבי) ל-threads אחרים, הם מסומנים ב-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 )
המלצה
צריך לצמצם את העבודה שדורשת הרבה משאבי מעבד ב-thread הראשי. שימוש ב-worker או בשרשורים ברקע לביצוע משימות שדורשות הרבה משאבי CPU.
מומלץ לצמצם את העבודה שדורשת הרבה קלט/פלט, כמו טעינה ממסד נתונים, ב-thread הראשי.
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. לדוגמה, אפשר לזהות את המקומות בקוד שבהם השרשור הראשי של האפליקציה עשוי להיות עמוס במשך יותר מ-5 שניות.