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