1. ANRの基礎知識
1.1. 発生原因
一言でまとめると、指定された時間内にやるべきことを完了できなかった場合、ANR が発生します。
1.2. ANR の分類
起こった場面からの分類:
- 入力イベントは 5 秒以上処理されていません。
- サービス処理タイムアウト、フォアグラウンドで 20 秒、バックグラウンドで 200 秒
- BroadcastReceiver 処理タイムアウト、フォアグラウンドで 10 秒、バックグラウンドで 60 秒
- ContentProvider の実行タイムアウト、比較的まれです
それが起こった理由によると:
- メインスレッドには、複雑なレイアウト、IO 操作など、時間のかかる操作が含まれます。
- バインダーピアによってブロックされました
- キルティング糸同期ロックブロック
- バインダーがいっぱいであるため、メインスレッドが SystemServer と通信できなくなります
- システムリソース(CPU/RAM/IO)を取得できません
プロセスの観点から見ると:
- 問題は現在のプロセスにあります。
メイン スレッド自体に時間がかかるか、メイン スレッドのメッセージ キューに時間のかかる操作があるか、
メイン スレッドがこのプロセスの他の子スレッドによってブロックされています。 - 問題はリモートプロセス (通常はバインダー呼び出しまたはソケット、その他の通信方法) にあります。
2. ANRのログ解析
2.1. ログの分類
ANR の問題が発生すると、通常はバグレポートが提出されます。
adb バグプロット xxx
最も重要なことは、生成されたバグレポートには anr の痕跡があるということですが、それを個別に取り出したい場合は、それで問題ありません。
adb プル /data/anr/traces.txt xxx
完全なバグレポートには、ANR の問題を分析するために重要な次の情報が含まれています。
ログ名 |
効果 |
コマンドの取得 |
システムログ |
ANR発生時点の情報、ANR発生前のCPU情報、および多数のシステムサービス出力情報が含まれます。 |
adb logcat –b システム |
main.log |
ANR が発生する前にアプリケーション自体が出力した情報が含まれており、アプリケーションが異常かどうかを分析するために使用できます。また、出力された GC 情報も含まれており、メモリのリサイクル速度を分析し、システムが異常状態であるかどうかを判断できます。メモリ不足またはメモリの断片化状態。 |
adb logcat –b main |
イベントログ |
AMSおよびWMSによって出力されるアプリケーションのライフサイクル情報が含まれており、ウィンドウの作成速度やフォーカス遷移ステータスの分析に使用できます。 |
adb logcat –b イベント |
カーネル.ログ |
ここには、カーネルによって出力される情報、LowMemoryKiller 強制終了プロセス、メモリの断片化またはメモリ不足、mmc ドライバの例外などの情報が含まれています。 |
なし |
それで、これらのログについてどう思いますか? 以下のケース 1 を参照してください
2.2. ケース 1: SP に時間がかかる問題により ANR が適用される
一般に、次のように、最初に ANR を検索して、最も直感的な情報を取得します。
06-16 16:16:28.590 1853 2073 E アクティビティマネージャー: com.android.camera の ANR (com.android.camera/.Camera) 06-16 16:16:28.590 1853 2073 E アクティビティマネージャー: PID: 27661 06-16 16 :16:28.590 1853 2073 E ActivityManager: 理由: 入力ディスパッチングがタイムアウトしました (com.android.camera/com.android.camera.Camera、タッチされたウィンドウが特定の入力イベントの処理を完了していないため、キー以外のイベントの送信を待機しています) 500.0 ミリ秒以上前に配信されました。待機キューの長さ: 24。待機キューのヘッド経過時間: 5511.1 ミリ秒。) 06-16 16:16:28.590 1853 2073 E ActivityManager: 負荷: 16.25 / 29.48 / 38.33 06-16 16:16: 28.590 1853 2073 E ActivityManager: 0 ミリ秒から 8058 ミリ秒後の CPU 使用率: 06-16 16:16:28.590 1853 2073 E ActivityManager: 58% 291/メディアサーバー: 51% ユーザー + 6.7% カーネル / 障害: 2457 マイナー 4 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 27% 317 06-16 16:16:28.590 1853 2073 E ActivityManager: 10% 539/sensors.qcom: 7.8% ユーザー + 2.6% カーネル /欠陥: 16 軽度 06-16 16:16:28.590 1853 2073 E ActivityManager: 27% 317/mm-qcamera-daemon: 21% ユーザー + 5.8% カーネル / 障害: 15965 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.4 % 288/debuggerd: 0% ユーザー + 0.3% カーネル / 障害: 21615 マイナー 87 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 17% 27661/com.android.camera: 10% ユーザー + 6.8% カーネル / 障害: 2412 マイナー 34 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 16% 1853/system_server: 10% ユーザー + 6.4% カーネル / 障害: 1754 マイナー 87 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManage r : 4.4% 277/surfaceflinger: 1.8% ユーザー + 2.6% カーネル / 障害: 14 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 4% 203/mmcqd/0: 0% ユーザー + 4% カーネル com。 android.phone: 1.9% ユーザー + 0.6% カーネル / 障害: 1148 マイナー 8 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 2.1% 2902/com.android.systemui: 1.6% ユーザー + 0.4% カーネル / 障害: 1272 マイナー 32 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 1.6% 3110/com.miui.whetstone: 1.6% ユーザー + 0% カーネル / 障害: 2614 マイナー 22 メジャー 06-16 16:16: 28.590 1853 2073 E ActivityManager: 0.8% 99/kswapd0: 0% ユーザー + 0.8% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 1.4% 217/jbd2/mmcblk0p25: 0% ユーザー + 1.4% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 1.4% 223/logd: 0.7% ユーザー + 0.7% カーネル / 障害: 4 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.8% 35/kworker 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.9% 12808/kworker/0:1: 0% ユーザー + 0.9% カーネル / u:2: 0% ユーザー + 0.8% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0% 3222/com.miui.sysbase: 0% ユーザー + 0% カーネル / 障害: 1314 マイナー 12 メジャー 06- 16 16:16:28.590 1853 2073 E ActivityManager: 0.8% 3446/com.android.nfc: 0.4% ユーザー + 0.3% カーネル / 障害: 1223 マイナー 9 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.7 % 10866/kworker/u:1: 0% ユーザー + 0.7% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.6% 642/mdss_fb0: 0% ユーザー + 0.6% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.6% 29336/kworker/u:7: 0% ユーザー + 0.6% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.4% 6/kworker/u:0: 0% ユーザー + 0.4% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.4% 22924/kworker/u:6: 0% ユーザー + 0.4% カーネル 2073 E ActivityManager: 0.3% 4421/mpdecion: 0 % ユーザー + 0.3% カーネル 06-16 16:16:28.590 1853 2073 E アクティビティマネージャー: 0.2% 276/サービスマネージャー: 0.1% ユーザー + 0.1% カーネル 06-16 16:16:28.590 1853 2073 E アクティビティマネージャー: 0.2% 289/怒り狂う: 0.2% ユーザー + 0% カーネル / 障害: 20 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.1% 4161/mcd: 0% ユーザー + 0% カーネル / 障害: 9 マイナー 1 メジャー 06-16 16 :16:28.590 1853 2073 E ActivityManager: 0.1% 3/ksoftirqd/0: 0% ユーザー + 0.1% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.1% 5/kworker/0:0H: 0% ユーザー+ 0.1% カーネル 06-16 16:16 :28.590 1853 2073 E ActivityManager: 0.1% 7/kworker/u:0H: 0% ユーザー + 0.1% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0% 215/flush-179:0: 0% ユーザー+ 0% カーネル 1853 2073 E ActivityManager: 0.1% 321/displayfeature: 0.1 % ユーザー + 0% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.1% 368/irq/33-cpubw_hw: 0% ユーザー + 0.1% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.1 % 403/qmuxd: 0% ユーザー + 0.1% カーネル / 障害: 60 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0% 3491/com.xiaomi.finddevice: 0% ユーザー + 0% カーネル / 障害: 706 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.1% 29330/ksoftirqd/1: 0% ユーザー + 0.1% カーネル 06-16 16:16:28.590 1853 2073 E ActivityManager: 96% 合計: 56 % ユーザー+ 29% カーネル + 6.3% iowait + 4.1% Softirq
ANR の問題が発生したとき、目の前にある痕跡は最初の犯罪現場ですか? ANR が発生したときに大量の情報が出力され、その時点で CPU および I/O リソースが比較的逼迫している場合、その時点でこのログ出力は遅延する可能性があります。遅延は 10 秒から 20 秒の範囲で発生する可能性があるため、より警戒する必要がある場合があります。例を挙げて 1 行ずつ説明してみましょう:
06-16 16:16:28.590 1853 2073 E ActivityManager: com.android.camera (com.android.camera/.Camera) の ANR。
この行は、ANR が発生した時刻が 06-16 16:16:28.590 であり、発生したプロセスが com.android.camera、具体的には com.android.camera/.Camera であることを学習します。1853 は systemserver の pid です。 2073 は ActivityManager スレッドであり、 ActivityManager の pid はシステム スレッドです。実際、イベント ログに対応する情報があり、キーワード am_anr を検索してください。
06-16 16:16:20.536 1853 2073 私は_anr : [0,27661,com.android.camera,952745541,入力ディスパッチがタイムアウトしました (com.android.camera/com.android.camera.Camera, 非送信の送信を待機しています)タッチされたウィンドウが 500.0 ミリ秒以上前に配信された特定の入力イベントの処理を完了していないため、キー イベントが発生しました。待機キューの長さ: 24。待機キューのヘッド経過時間: 5511.1 ミリ秒。)]
ここから、ANR の時点、タイプ、プロセス PID、プロセス名などを決定することもできます。次の行に進みます。
06-16 16:16:28.590 1853 2073 E アクティビティマネージャー: PID: 27661
この行は、ANR プロセスの pid が 27661 であることを学習します。特殊なケースでは、pid が 0 の場合、プロセスが LowMemoryKiller によって強制終了されたか、ANR が発生する前にクラッシュしたことを意味します。この場合、システム ブロードキャストを受信できません。またはキー メッセージであるため、ANR が発生します。
06-16 16:16:28.590 1853 2073 E ActivityManager: 理由: 入力ディスパッチがタイムアウトしました (com.android.camera/com.android.camera.Camera、タッチされたウィンドウが特定の処理を完了していないため、非キー イベントの送信を待機しています) 500.0 ミリ秒以上前に配信された入力イベント。待機キューの長さ: 24。待機キューのヘッド経過時間: 5511.1 ミリ秒。)
この行は、ANR の理由が入力ディスパッチのタイムアウトであることを学習します。
06-16 16:16:28.590 1853 2073 E アクティビティマネージャー: 負荷: 16.25 / 29.48 / 38.33
この行はCPU の負荷を示します。Linux オペレーティング システムでは、uptime を入力することで一定期間の負荷を取得することもできます。
稼働時間 20:09:54 71 日間、10:48、1 ユーザー、負荷平均: 0.99、0.78、0.86
では、負荷とは何を意味するのでしょうか?Load の後の 3 つの数値は、それぞれ 1 分、5 分、15 分におけるシステムの平均負荷を意味します。CPU が完全にアイドル状態の場合、平均負荷は 0 になります。CPU ワークロードが飽和している場合、平均負荷は 1 です。負荷は、システム負荷が重すぎるかどうかを判断するために使用できます。鮮やかな比喩があります: CPU を橋に見立ててください。橋には車線が 1 つだけあります。すべての車両はこの車線を通過しなければなりません。システム負荷は 0 です。つまり、橋には 1 台の車もありません。システム負荷は 0.5 で、これは橋の半分のセクションに車両が存在することを意味し、システム負荷は 1.0 で、橋のすべてのセクションに車両が存在することを意味します。これは、橋が「満杯」であることを意味します。システム負荷は 2.0 です。これは車両が多すぎることを意味し、橋は満杯 (100%) であり、橋に入るのを待っている車両が 2 倍あります。橋の交通容量は CPU の最大作業負荷であり、橋上の車両は CPU による処理を待っているプロセスです。
経験則として、
システム負荷が常に 0.7 を超えている場合は、問題が何であるかを調査し、状況の悪化を防ぐ必要があります。
システム負荷が 1.0 を超え続ける場合は、この値を下げる解決策を見つける必要があります。
システム負荷が 5.0 に達すると、システムに重大な問題があることを示します。
1 分間のみのシステム負荷が 1.0 を超え、他の 2 つの期間が 1.0 未満である場合、これはそれが一時的な現象にすぎず、問題は深刻ではないことを示します。
(CPU コアの数を調整した後) 15 分以内に平均システム負荷が 1.0 を超える場合、問題が一時的な現象ではなく継続していることを示します。したがって、コンピュータの正常な動作の指標として、主に「15 分間のシステム負荷」を観察する必要があります。
現在の携帯電話はマルチコア CPU アーキテクチャを採用しており、8 コアが多いため、CPU の処理能力は 8 倍になります。各コアの実行時間は、/sys/devices/system ファイルから取得できます。 / cpu/cpu%d/cpufreq/stats/time_in_state から読み取り、%d は CPU のコアを表します。ファイルには、起動からファイルの読み取りまでの各周波数での CPU の実行時間が記録されます (単位: 10 ミリ秒)。
adb shell cat /sys/devices/system/cpu/cpu1/cpufreq/stats/time_in_state を使用して周波数を確認します。
adb shell cat /sys/devices/system/cpu/cpu1/cpufreq/stats/time_in_state を使用して 周波数時間を表示します 652800 1813593 1036800 46484 1401600 521974 1689600 2956667 1843200 83065 1958400 5 3516 2016000 251693
負荷の詳細については、「Linux システム負荷について」を参照してください。ただし、あまり詳しく説明しないでください。
06-16 16:16:28.590 1853 2073 E ActivityManager: 0ms から 8058ms 以降の CPU 使用率: 06-16 16:16:28.590 1853 2073 E ActivityManager: 58% 291/mediaserver: 51% ユーザー + 6.7% カーネル / 障害: 2457 マイナー 4 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 27% 317/mm-qcamera-daemon: 21% ユーザー + 5.8% カーネル / 障害: 15965 マイナー 06-16 16:16:28.590 1853 2073 E ActivityManager: 0.4% 288/debuggerd: 0% ユーザー + 0.3% カーネル / 障害: 21615 マイナー 87 メジャー 06-16 16:16:28.590 1853 2073 E ActivityManager: 17% 27661/com.android.camera: 10% ユーザー + 6.8 % カーネル / 障害: 2412 マイナー 34 メジャー .... 06-16 16:16:28.590 1853 2073 E ActivityManager: 96% 合計: 56% ユーザー + 29% カーネル + 6.3% iowait + 4.1% Softirq .....
このログでは、ANR が発生したときの上位プロセスの CPU 使用率を取得できます。ユーザーはユーザー空間を表し、カーネルはカーネル空間を表します。一般に、次のルールが適用されます。
- kswapd0 の CPU 占有率が高いと、システム全体の動作が遅くなり、さまざまな ANR が発生します。問題を「メモリの最適化」に転送し、最適化するように依頼してください。
- logd の CPU 使用率が高いと、LOG を出力する各プロセスの操作がブロックされ、実行が非常に遅くなるため、システムのフリーズや ANR が発生する可能性があります。
- Vold は CPU を大量に消費し、システム フリーズや ANR を引き起こす可能性があります。まず、ストレージを担当しているかどうかを調べてください。
- qcom.sensor CPU 使用率が高すぎるため、遅延が発生する可能性があります。システムを調査してください。
- アプリケーション自体の CPU 使用率が高く、アプリケーションに問題が発生する可能性が高い
- システムの CPU 使用率は高くありませんが、メインスレッドがロックを待機しているため、アプリケーションに問題が発生する可能性が高くなります。
- アプリケーションは D 状態にあり、ANR が発生します。最後の操作が冷蔵庫の場合、アプリケーションはフリーズします。これは通常、消費電力の最適化によって発生します。
上記のログから ANR の基本情報が得られましたが、どこで障害が発生しているかを調べるには、トレース ファイルを使用する必要があります。通常は anr ディレクトリにあります。次のように、このトレース ファイル内のメイン スレッドのスタックを検索します。
----- pid 27661 at 2017-06-16 16:16:20 ----- コマンドライン: com.android.camera "main" prio=5 tid=1 待機中 | グループ = "メイン" sCount = 1 dsCount = 0 obj = 0x75a4b5c8 self = 0xb4cf6500 | sysTid=27661 nice=-10 cgrp=デフォルト sched=0/0 ハンドル=0xb6f6cb34 | 状態=S schedstat=( 11242036155 8689191757 38520 ) utm=895 stm=229 コア=0 HZ=100 | スタック=0xbe4ea000-0xbe4ec000 スタックサイズ=8MB | 保持された mutexes= で java.lang.Object.wait!(ネイティブ メソッド) - java.lang.Thread.parkFor$(Thread.java:1220) で<0x09e6a059> (java.lang.Object) を待機 - ロックされた <0x09e6a059 > (java.lang.Object) at sun.misc.Unsafe.park(Unsafe.java:299) at java.util.concurrent.locks.LockSupport.park(LockSupport.java: java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:810) で java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:970) で java.util.concurrent.locks.AbstractQueu edSynchronizer.acquireShared割り込み可能(AbstractQueuedSynchronizer.java:1278) java.util.concurrent.CountDownLatch.await(CountDownLatch.java:203) で android.app.SharedPreferencesImpl$EditorImpl$1.run(SharedPreferencesImpl.java:366) で android.app.QueuedWork.waitToFinish (QueuedWork.java:88) android.app.ActivityThread.handleStopActivity(ActivityThread.java:3605) android.app.ActivityThread.access$1300(ActivityThread.java:153) android.app.ActivityThread$H.handleMessage(ActivityThread.java:1399) で android.os.Handler.dispatchMessage(Handler.java:102) で android.os.Looper.loop(Looper.java:154) で android で。 app.ActivityThread.main(ActivityThread.java:5528) java.lang.reflect.Method.invoke!(ネイティブ メソッド) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:740) com .android.internal.os.ZygoteInit.main(ZygoteInit.java:630)
いくつかのフィールドの意味を説明する
分野 |
意味 |
時間=1 |
スレッド番号 |
sysTid=27661 |
メインスレッドのスレッド番号とプロセス番号が同じである |
待っている |
スレッド状態。state=D の場合、最下層がブロックされていることを意味します。state はスレッド状態でもあります。 |
ニース |
nice 値が小さいほど優先度が高くなります。ここではメインスレッドなので nice=-10 となっており、優先度が非常に高いことがわかります。 |
スケジュール統計 |
括弧内の 3 つの数字は、順に実行時間、実行可能時間、切り替え時間です。実行時間: CPU 実行時間、単位は ns。実行可能時間: RQ キューの待機時間 (ns)。切り替え時間: CPU スケジューリング切り替えの数 |
うーん |
スレッドがユーザーモードで実行される時間、単位は一瞬です |
stm |
スレッドがカーネル モードで実行される時間は、単位は一瞬です |
sカウント |
このスレッドが一時停止された回数 |
dsカウント |
デバッガによってスレッドが中断された回数。プロセスがデバッグされると、sCount は 0 にリセットされます。デバッグ後、正常に中断されたかどうかに応じて sCount は増加しますが、dsCount は 0 にリセットされません。 dsCount も使用できます。このスレッドがデバッグされているかどうかを判断するために使用されます。 |
自己 |
スレッド自体のアドレス |
スレッドの状況について話しましょう
州 |
価値 |
説明する |
THREAD_ZOMBIE |
0 |
終了しました |
THREAD_RUNNING |
1 |
実行可能または現在実行中 |
THREAD_TIMED_WAIT |
2 |
Object.wait() の TIMED_WAITING |
THREAD_MONITOR |
3 |
モニター上でブロックされました |
THREAD_INITIALIZING |
5 |
割り当てられてまだ実行されていない |
THREAD_STARTING |
6 |
まだスレッドリストに載っていない状態で開始されました |
THREAD_NATIVE |
7 |
JNI ネイティブ メソッドではオフ |
THREAD_VMWAIT |
8 |
VMリソースを待機中 |
THREAD_SUSPENDED |
9 |
通常は GC またはデバッガによって一時停止されます |
では、この問題をどのように解決すればよいでしょうか? 上記の基本的な導入とトレース ファイルを通じて、ブロックされているポイントは次のとおりであることがわかります。
java.util.concurrent.CountDownLatch.await(CountDownLatch.java:203) で android.app.SharedPreferencesImpl$EditorImpl$1.run(SharedPreferencesImpl.java:366) で android.app.QueuedWork.waitToFinish(QueuedWork.java:88)で android.app.ActivityThread.handleStopActivity(ActivityThread.java:3605) android.app.ActivityThread.access$1300(ActivityThread.java:153) で
まず QueuedWork.waitToFinish を見てみましょう
77 /** 78 * 非同期操作を終了するか、完了するまで待機します。 79 * (例: SharedPreferences$Editor#startCommit の書き込み) 80 * 81 * Service コマンド処理後、Activity 基本クラスの onPause() から呼び出されます 82 * BroadcastReceiver の onReceive、Service コマンド処理後、 83 * など (非同期作業が失われることはありません) 84 */ 85 public static void waitToFinish() { 86 終了まで実行可能; //等全て待って完了する仕事を完了 87 while ((toFinish = sPendingWorkFinishers.poll()) != null) { 88 toFinish.run(); 89 } 90 }
QueuedWork.waitToFinish は、非同期タスクの実行が確実に完了するように、Activity の onPause または BroadcastReceiver の onReceive の後に呼び出されます。waitToFinish では、sPendingWorkFinishers で完了を待っているすべてのタスクを繰り返し、完了するまで待ちます。SharedPreferencesImpl.apply を見てみましょう。このメソッドは、ファイル システムへの書き込みを待機しているタスクを QueuedWork の完了待ちキューに入れます。
361 public void apply() { 362 Final MemoryCommitResult mcr = commitToMemory(); 363 Final Runnable awaitCommit = new Runnable() { 364 public void run() { 365 try { 366 mcr.writeToDiskLatch.await(); 367 } catch (InterruptedException無視されます) { 368 } 369 } 370 }; 371 //ファイルシステムへの書き込みを待っているタスクを QueuedWork の待機キューに入れます 372 QueuedWork.add(awaitCommit); 373 ... ... ... ... ... ... 388 }
apply メソッド自体はすぐに戻ることができますが、アクティビティの onPause が呼び出されると、ファイル システムへの書き込みタスクが完了するまで待機します。つまり、apply 自体は呼び出しスレッドをブロックしませんが、待機時間をメインスレッドに転送します。したがって、書き込みタスクの実行が遅く、アクティビティ、サービス、ブロードキャストの sp 操作がライフサイクルの終了時に完了しない場合、メインスレッドがブロックされ、ANR が発生します。分析の現時点では、これがシステムの問題であり、アプリが無力であることは明らかですが、幸いなことに、この問題は Xiaomi の携帯電話では緩和されており、解決策は公開されません。一般に、トレースを確認するためのルールは次のとおりです。
- ANR が発生した場合、トレース上で該当するプロセスが見つからない場合は、アプリケーションのクラッシュにより Android ランタイムがシャットダウンしているかどうかを確認し、シャットダウンしている場合は、この時点でシャットダウンした理由を確認してください。
- ANR はアプリケーションで発生します。メイン スレッドが getContentProvider を実行している場合、別のアプリケーションの ContentProvider を要求しています。このとき、対象の ContentProvider のホスト プロセスをチェックして、それが何を行っているかを確認します。
- メインスレッドがデータベース操作またはネットワークリクエストを実行する場合、アプリケーション自体に問題があるはずです。
- メインスレッドが他のスレッドが保持するロックを待機し、ターゲットスレッドがデータベース操作またはネットワークリクエストを実行する場合、それはアプリケーション自体に問題があります。
ここでは、ANR 分析の基本プロセスに慣れるためのケースから始めます。上記のルーチンをここで要約しましょう。
- バグレポートを取得し、ANR を検索して、発生時間とプロセスを確認します。
- プロセスに従ってメインスレッドのトレースを見つけ、ブロックされている場所を見つける
- ソース コードに基づく分析と解決
もちろん、これら 2 つの手順を通じて、ANR の原因を突き止めることができます。これは、比較的幸運であることを示していますが、ほとんどの場合はこのようにはなりません。
上記では、システムの問題によって引き起こされた ANR を分析しました。ここで、私のアプリは何も機能しなかったと思われるかもしれませんが、ANR が発生しました。将来的には、システムを直接非難することができます。いいえ、特定の問題はまだ分析する必要があります詳細に説明します。システムを疑うには、証拠が必要です。証拠はどこから来たのか、それともログから来たのでしょうか。3 番目のセクション、時間のかかるシステムの分析計画に進みます。
3. システムに時間のかかる分析計画
システムは、時間のかかる分析操作を実行しています。一部の携帯電話メーカーでは、ログにその他の機能強化が加えられています。より一般的な機能のいくつかを以下に示します。
3.1、バインダー_サンプル
- A. 機能説明: 各プロセスのメインスレッドのバインダートランザクションの時間のかかり具合を監視し、閾値を超えた場合に該当するターゲットコール情報を出力しますデフォルトでは1000msでオンになります。
- B.log格式: 52004 binding_sample (descriptor|3),(method_num|1|5),(time|1|3),(blocking_package|3),(sample_percent|1|6)
- C.log の例:
2754 2754 I バインダー_サンプル: [android.app.IActivityManager,35,2900,android.process.media,5]
上記のログから、 1. メイン スレッド 2754;
2. android.app.IActivityManager インターフェイスを実行すると結論付けることができます。
- 対応するメソッド コード =35 (つまり STOP_SERVICE_TRANSACTION)、
- 所要時間は2900ミリ秒です。
- このブロックが配置されているパッケージは android.process.media で、最後のパラメータはサンプル率です (あまり価値はありません)。
3.2、dvm_lock_sample
- A. 機能説明: ロック待ちスレッドのブロック時間が閾値を超えた場合、現在のロック状態を出力します。
- B.log格式: 20003 dvm_lock_sample (プロセス|3),(メイン|1|5),(スレッド|3),(時間|1|3),(ファイル|3),(行|1|5),(所有者ファイル|3)、(所有者ライン|1|5)、(サンプルパーセント|1|6)
- C.log の例:
dvm_lock_sample: [system_server,1,Binder_9,1500,ActivityManagerService.java,6403,-,1448,0]
これは、ActivityManagerService.java の 6403 行目まで実行された system_server: Binder_9 が AMS ロックを待機していて、そのロックが同じファイルの 1448 行目で保持されているため、Binder_9 スレッドが 1500 ミリ秒ブロックされていることを意味します。
3.3、バインダー不足
- A. 機能説明: system_server などのプロセスのスレッドプールが枯渇し、アイドルスレッドがなくなった場合、バインダ通信がスタベーション状態となり、スタベーション状態が一定の閾値を超えた場合に情報を出力します。
- B. クラウド制御パラメータ:persist.sys.binder.starvation (デフォルト値 16ms)
- C.log の例:
1232 1232 "バインダー スレッド プール (16 スレッド) が 100 ミリ秒間枯渇しました"
- D.log 分析: system_server プロセスのスレッド プールが最大 100 ミリ秒にわたっていっぱいになります。
通常、この情報を取得すると、問題の原因がシステムにあるのかアプリにあるのかを判断するのに役立ちます。以下のケース 2 を参照してください。
3.4. ケース 2: Crazy Binder Call によりアプリケーション ANR が発生する
ANR を検索
08-28 18:54:00.110 1000 1825 1848 E ActivityManager: com.jeejen.family の ANR (com.jeejen.family/com.jeejen.home.launcher.ShoppingActivity) 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: PID: 20576 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 理由: 入力ディスパッチがタイムアウトしました (com.jeejen.family/com.jeejen.home.launcher.WelcomeActivity、キー以外のイベントの送信を待機しています。タッチされたウィンドウは、500.0 ミリ秒以上前に配信された特定の入力イベントの処理を完了していません。待機キューの長さ: 2。待機キューのヘッド経過時間: 10064.4 ミリ秒。) 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 親: com.jeejen.family/com.jeejen.home.launcher.WelcomeActivity 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 負荷: 1.25 / 1.1 / 1.37 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: CPU 使用率 5166 ミリ秒から 0 ミリ秒前 (2018-08-28 18:53:51.270 から 2018-08-28 18:53:56.436): 08-28 18 : 54:00.110 1000 1825 1848 E アクティビティマネージャー: 7.7% 1825/system_server: 5.6% ユーザー + 2.1% カーネル / 障害: 1329 マイナー 08-28 18:54:00.110 1000 1825 1848 E アクティビティマネージャー: 3.6% 20683 /com.jeejen.family :pushcenter_pushservice: 3% ユーザー + 0.5% カーネル / 障害: 542 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 2.7% 4114/cnss_diag: 1.9% ユーザー + 0.7% カーネル 08-28 18:54:00.1 10 1000 1825 1848 E ActivityManager: 2.1% 422/kworker/u16:7: 0% ユーザー + 2.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 1.9% 20830/com.jeejen.family:store: 1.3 % ユーザー + 0.5% カーネル / 障害: 199 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 1.7% 20608/com.jeejen.family:pushcenter: 1.1% ユーザー + 0.5% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 1 .5% 725 /[email protected]: 0.7% ユーザー + 0.7% カーネル / 障害: 1 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.9% 3538/com.android.systemui: 0.7% ユーザー+ 0.1% カーネル / 障害: 11 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.5% 241/crtc_commit:111: 0% ユーザー + 0.5% カーネル 08-28 18:54:00.110 1000 1825 1 848E ActivityManager: 0.5% 419/kworker/u16:4: 0% ユーザー + 0.5% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.5% 786/surfaceflinger: 0.5% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E アクティビティマネージャー: 0.3% 185/IPCRTR_dsps_sme: 0% ユーザー + 0.3% カーネル 08-28 18:54:00.110 1000 1825 1848 E アクティビティマネージャー: 0.3% 730 /android.ハード ウェア.wifi @1.0-サービス: 0.1% ユーザー + 0.1% カーネル / 障害: 28 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.3% 820/dsps_IPCRTR: 0% ユーザー + 0.3% カーネル 08-28 18:54 :00.110 1000 1825 1848 E ActivityManager: 0.3% 1147/msm_irqbalance: 0.1% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.3% 4113/sugov:0: 0 % ユーザー + 0.3% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 10/rcuop/0: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 18/ ksoftirqd /1 : 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0% 34/ksoftirqd/3: 0% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0% 53/rcuop/5 : 0% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0% 61/rcuop/6: 0% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager : 0.1% 242/crtc_event:111: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 538/ueventd: 0.1% ユーザー + 0% カーネル 08-28 18:54: 00.110 1000 1825 1848 E ActivityManager: 0.1% 577/jbd2/sda22-8: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 591/logd: 0.1% ユーザー+0%カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 719/[email protected]: 0.1% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager : 0.1% 928/サーマルエンジン: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 3490/cds_mc_thread: 0% ユーザー + 0.1% カーネル 08-28 18:54: 00.110 1000 1825 1848 E ActivityManager: 0.1% 3491/cds_ol_rx_threa: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 3680/com.android.phone: 0 % ユーザー + 0.1%カーネル / 障害: 16 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 4248/com.miui.daemon: 0.1% ユーザー + 0% カーネル / 障害: 4 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 4488/com.miui.powerkeeper: 0.1% ユーザー + 0% カーネル / 障害: 10 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager : 0.1% 5545/com.lbe.security.miui: 0% ユーザー + 0.1% カーネル / 障害: 6 マイナー 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 6490/kworker/u17:2: 0%ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 7535/kworker/u16:15: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityMan年齢 : 0% 7723/kworker/3:5: 0% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 15111/kworker/1:0: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E アクティビティマネージャー: 0.1% 15138/kworker/3:0: 0% ユーザー + 0.1% カーネル 08-28 18:54:00.110 1000 1825 1848 E アクティビティマネージャー: 0% 19857 / kworker /0:3: 0% ユーザー + 0% カーネル 08-28 18:54:00.110 1000 1825 1848 E ActivityManager: 0.1% 20492/kworker/5:3: 0% ユーザー + 0.1% カーネル 08-28 18:54: 00.110 1000 1825 1848 E ActivityManager: 3.8% 合計: 2% ユーザー + 1.1% カーネル + 0% iowait + 0.3% irq + 0.1% Softirq
上記のルーチンによると、すべては比較的正常です。発生時刻はおそらく 08-28 18:54:00.110 です。メイン スレッドのトレースを見ています。
----- pid 20576 at 2018-08-28 18:53:56 ----- コマンドライン: com.jeejen.family "main" prio=5 tid=1 ネイティブ | グループ = "メイン" sCount = 1 dsCount = 0 flags = 1 obj = 0x77ffca18 self = 0xecfce000 | sysTid=20576 nice=-10 cgrp=デフォルト sched=0/0 ハンドル=0xf0bf2494 | 状態=S schedstat=( 628294395 402363898 957 ) utm=42 stm=20 コア=4 HZ=100 | スタック=0xff5fe000-0xff600000 スタックサイズ=8MB | 保持されたミューテックス = カーネル: (/proc/self/task/20576/stack を読み取れませんでした) ネイティブ : #00 pc 00053cfc /system/lib/libc.so (__ioctl+8) ネイティブ: #01 pc 00021cd3 /system/lib /libc.so (ioctl+30) ネイティブ: #02 pc 0003d3f5 /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+204) ネイティブ: #03 pc 0003dde3 /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+26) ネイティブ: #04 pc 0003713d /system/lib/libbinder.so ( android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36) ネイティブ: #05 pc 000c3cf1 /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject) *, int, _jobject*, _jobject*, int)+200) android.os.BinderProxy.transactNative(ネイティブ メソッド) android.os.BinderProxy.transact(Binder.java:1127) android.net.wifi.IWifiManager $Stub$Proxy.getConnectionInfo(IWifiManager.java:1441) android.net.wifi.WifiManager.getConnectionInfo(WifiManager.java:1778) org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate.getWifiInfoLocked(NetworkChangeNotifierAutoDetect.java:28) org.chromium.net.NetworkChangeNotifierAutoDetect$WifiManagerDelegate.getWifiSsid(NetworkChangeNotifierAutoDetect.java:22) - ロックされた <0x0f4edae7> (java.lang.Object) ) org.chromium.net.NetworkChangeNotifierAutoDetect.getCurrentNetworkState(NetworkChangeNotifierAutoDetect.java:67) で org.chromium.net.NetworkChangeNotifierAutoDetect.<init>(NetworkChangeNotifierAutoDetect.java:21) で org.chromium.net.NetworkChangeNotifier.setAutoDetectConnectivityStateInternal(NetworkChangeNotifier. java:61)
バインダー呼び出しがブロックされているようで、呼び出しインターフェイスは IWifiManager.getConnectionInfo() です。バインダー呼び出しなので、binder_sample を確認してください。
08-28 18:54:01.384 10171 20576 20576 I バインダー_サンプル: [android.net.wifi.IWifiManager,24,16004,com.jeejen.family,100] 08-28 18:54:04.868 10171 20576 20576 I バインダー_sたっぷり: [ android.net.wifi.IWifiManager,24,3479,com.jeejen.family,100] 08-28 18:56:12.712 10171 21885 21885 I バインダー_サンプル: [android.net.wifi.IWifiManager,24,8963,com.jeejen .ファミリー,100]
ANR に近づくと、IWifiManager インターフェイスを使用したバインダー呼び出しに時間がかかることがわかりますが、これはシステム上の理由でしょうか? 次に、彼のピア Sysytem のコードを見てみましょう。
・動物でみる動物の心理占い無料サイト結果1763 ・ 動物でみる動物の心理占い無料サイト結果 1764 ・動物でみる動物の心理占い無料サイト結果1765 ・動物でみる動物の心理占い無料サイト結果1766 ・動物 でみる動物の心理占い無料サイト結果 1769 1770 mLog.trace("getConnectionInfo uid=%").c(Binder.getCallingUid()).flush(); 1771 /* 1772 * ステータス要求をサプリカントに送信して、最新の情報を入手していることを確認してください。 ・動物でみる動物の心理占い無料サイト結果 1774 1776 }
・動物でみる動物の心理占い無料サイト 結果1521 1523 結果を返します。 1524 }
getConnectionInfo は、wifiService を通じて直接 wifiStateMachine の syncRequestConnectionInfo を呼び出します。この部分の実装はブロックされません。Binder がいっぱいですか? これはトレースからは見えないのですが、何が起こっているのでしょうか?この問題を再現しようとしましたが、幸いにも再現は比較的簡単でした。
09-04 18:24:29.182 D/WifiStateMachine( 1312): syncRequestConnectionInfo/in SSID: MIOffice-5G、BSSID: 70:3a:0e:2c:bb:f1、MAC: 80:ad:16:4c:0b: fe、サプリカントの状態: COMPLETED、RSSI: -44、リンク速度: 400Mbps、周波数: 5180MHz、ネット ID: 0、従量制ヒント: false、スコア: 60 09-04 18:24:29.182 D/WifiStateMachine( 1312): syncRequestConnectionInfo /out SSID: MIOffice-5G、BSSID: 70:3a:0e:2c:bb:f1、MAC: 80:ad:16:4c:0b:fe、サプリカントの状態: COMPLETED、RSSI: -44、リンク速度: 400Mbps 、周波数: 5180MHz、ネット ID: 0、メーターヒント: false、スコア: 60
メインスレッドが上記のログを大量に出力しており、ミニマリストデスクトップがこのインターフェースを 1 分間に 160 回呼び出したため、SystemServer がタイムリーにアプリに応答できなくなり、アプリ自体のエラーが発生したことが判明しました。 ANR。Binder 呼び出しによって引き起こされる ANR などの問題は非常に一般的であり、ブロックされるリスクがあります。現時点では、Binder 呼び出しを非同期で実行することを試みることができます。第 2 に、短期間に大量の Binder 呼び出しを行わないでください。この動作により、アプリ自体に問題が発生する可能性があり、最悪の場合、システムがクラッシュして Watchdog で再起動される可能性があります。
3.5. ケース 3: ブロードキャスト タイムアウトによりアプリの ANR が発生する
ケース 3 に進みましょう。上記のルーチンに従って、まずイベント ログで ANR が発生した時刻を確認します。
12-17 06:02:14.463 1566 1583 私は_anr : [0,8769,com.android.updater,952680005,意図のブロードキャスト { act=android.intent.action.BOOT_COMPLETED flg=0x9000010 cmp=com.android.updater/ .BootCompletedReceiver (追加機能あり) }]
ANR が発生した時刻は am_anr です。その時点は 12-17 06:02:14.463 です。引き続きログを確認します。
12-17 06:02:00.370 1566 1583 W BroadcastQueue: ブロードキャスト BroadcastRecord のタイムアウト{21ef8c2 u0 android.intent.action.BOOT_COMPLETED} - レシーバー=android.os.BinderProxy@2a6c365、60006 ミリ秒前に開始しました 12-17 06:02: 00.370 1566 1583 W BroadcastQueue: タイムアウト中の受信者: ResolveInfo{5a8283a com.android.updater/.BootCompletedReceiver m=0x108000} 12-17 06:02:00.370 1566 1583 私は_broadcast_discard_app: [0,35584194,android.intent.action] .BOOT_COMPLETED、 49,ResolveInfo{5a8283a com.android.updater/.BootCompletedReceiver m=0x108000}]
ただし、ANR が 12-17 06:02:00.370 で発生していることがわかりました。これは、イベント ログの時間はおおよその値であり、システム リソースが逼迫しているためにある程度の遅延が発生する可能性があることを示しています。ANR を受信するのは android.intent.action.BOOT_COMPLETED ブロードキャストであるため、手がかりを追跡できます。
12-17 06:01:00.383 1566 3524 I ActivityManager: ブロードキャスト用に proc 8769:com.android.updater/9802 を開始します com.android.updater/.BootCompletedReceiver caller=null
ブロードキャスト プロセスは 12-17 06:01:00.383 に開始されました。
12-17 06:01:36.721 8769 8769 D BootCompletedReceiver: onReceive android.intent.action.BOOT_COMPLETED 12-17 06:02:14.725 8769 8769 D UpdateService: onCreate
12-17 06:01:36.721 に、クライアントの BootCompletedReceiver onReceiver メソッドがコールバックを開始し、次に onReceive が UpdateService を開始します。UpdateService.onCreate を呼び出す時間は 12-17 06:02:14.725 です。上記の分析に基づいて、2 つの予備的な質問があります。
ブロードキャストは 12-17 06:01:00.383 に開始され、ブロードキャストの onReceiver メソッドは 12-17 06:01:36.721 にコールバックを開始しました。ANR 時間は 12-17 06:02:00.370 でした。 36 秒後に開始しますか? bootcompleted ブロードキャストを受信したところですが、これ自体異常です。次に、ブロードキャストを通じて UpdateService を開始するのに 1 分以上かかるのはなぜですか? この点を分析した結果、App 学生はこれ以上の分析は不可能であり、その原因の 80% はシステムにあると考えており、CPU 統計から判断すると、特定のプログラムの過剰な使用が原因であると考えられます。以下のログを掲載します。
12-17 06:02:19.286 1566 1583 E アクティビティマネージャー: com.android.updater の ANR 12-17 06:02:19.286 1566 1583 E アクティビティマネージャー: PID: 8769 12-17 06:02:19.286 1566 1583 E アクティビティ管理r:理由: インテントのブロードキャスト { act=android.intent.action.BOOT_COMPLETED flg=0x9000010 cmp=com.android.updater/.BootCompletedReceiver (追加機能あり) } 12-17 06:02:19.286 1566 1583 E ActivityManager: Load: 0.0 / 0.0 / 0.0 12-17 06:02:19.286 1566 1583 E ActivityManager: 0 ミリ秒から 18846 ミリ秒後の CPU 使用率 (2017-12-17 06:02:00.379 から 2017-12-17 06:02:19.224): 12-17 06 :02:19.286 1566 1583 E ActivityManager: 195% 6142/com.immomo.momo: 195% ユーザー + 0% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager: 2.3% 8170/com.tencent.mm: 2.3 % ユーザー + 0% カーネル / 障害: 448 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.7% 1566/system_server: 0.4% ユーザー + 0.3% カーネル / 障害: 150 マイナー 1 メジャー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.4% 90 / kworker/u16:3: 0% ユーザー + 0.4% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.3% 4704/com.tencent.mm:push: 0.1% ユーザー + 0.2% カーネル / 障害: 116 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.3% 8769/com.android.updater: 0.2% ユーザー + 0.1% カーネル / 障害: 1600 マイナー 2 メジャー 12-17 06:02:19.286 1566 1583 E ActivityManager : 0.2% 4790/com.tencent.mm:patch: 0.2% ユーザー + 0% カーネル / 障害: 748 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.2% 329/mmc-cmdqd/0: 0% ユーザー+ 0.2% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.2% 5429/com.tencent.mm:push: 0% ユーザー + 0.1% カーネル / 障害: 17 マイナー 12-17 06:02: 19.286 1566 1583 E ActivityManager: 0.2% 5435/com.tencent.mm:patch: 0.2% ユーザー + 0% カーネル / 障害: 82 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.2% 8712/com.tencent.mm:exdevice: 0.1 % ユーザー + 0% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.1% 432/logd: 0.1% ユーザー + 0% カーネル / 障害: 4 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager : 0.1% 844/msm_irqbalance: 0% ユーザー + 0.1% カーネル / 障害: 4 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.1% 7580/kworker/u16:2: 0% ユーザー + 0.1% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager:0.1%7/rcu_preempt:0%user + 0.1%kernel 12-17 06:02:19.286 1566 1583 e Activitymanager:0.1%1240/zygote:0%ユーザー + 0.1 % カーネル / 障害: 84 マイナー 12-17 06:02:19.286 1566 1583 E ActivityManager: 0% 3216/com.xiaomi.simactivate.service: 0% ユーザー + 0% カーネル / 障害: 5 マイナー 12-17 06:02 :19.286 1566 1583 E ActivityManager: 0.1% 8645/kworker/7:0: 0% ユーザー + 0.1% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager: 0.1% 8730/kworker/4:2: 0% ユーザー+ 0.1% カーネル 12-17 06:02:19.286 1566 1583 E ActivityManager: 0% 45/rcuop/4: 0% ユーザー + 0% カーネル
ただし、CPU 占有率 195% は高くありません。マルチコアでは、各コアの最大占有率は 100% (8 コアの占有率は 800% です)。次に、負荷: 0.0 / 0.0 / 0.0。負荷は高くありません。 15 分間アクティブです。0 です。停止していますか? このログは完全に正確ではないようです。ただし、Xiaomi端末ではANR監視が強化され、以下のようなログが出力されます。
12-17 06:02:14.693 8769 8769 W MIUI-BLOCK-MONITOR: メッセージ { when=-36s107ms what=113 obj=ReceiverData{intent=Intent { act=android.intent.action.BOOT_COMPLETED flg=0x9000010 cmp=com .android.updater/.BootCompletedReceiver (追加機能あり) } packageName=com.android.updater resultCode=0 resultData=null resultExtras=null} target=android.app.ActivityThread$H planTime=1513461660613dispatchTime=1513461696720finishTime=0 } 74080ミリ秒かかりましたディスパッチ後は 37973ms かかりました。
さらに、分析を容易にするために、各メッセージの各ステータスの時点を記録します。
- when: メッセージが実行されるべき時から anr が発生するまでの時間
- planTime: メッセージ プランが実行される時点
- dispatchTime: メッセージが実際に実行される時点
- finishTime: メッセージが完了した時点。
メッセージの実行時間は次のように計算されます: -when-(dispatchTime-planTime)=0 では、これは何を意味しますか? これは、メッセージ 113 が実行を開始しようとしていたが、実行を開始する前に ANR が発生し、メイン スレッドの Looper メッセージ キューで 36 秒間待機したことを意味します。このログにはメインスレッドの痕跡はなく、このメッセージはまだ実行されていないことがわかるため、影響はありません。では、この 36 秒間に何をしているのでしょうか? 以下にさらにログがあります。
12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: バインダーの呼び出しに 3973 ミリ秒かかりました。 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: java.lang.Throwable 12-17 06:01 :29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.os.AnrMonitor.checkBinderCallTime(AnrMonitor. java:591) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.os.BinderProxy.transact(Binder.java:623) 12-17 06:01: 29.334 8769 8769 W MIUI-BLOCK -MONITOR: android.content.pm.IPackageManager$Stub$Proxy.getApplicationInfo(IPackageManager.java:2658) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.ApplicationPackageManager.getApplicationInfoAsUser( ApplicationPackageManager.java:340) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: で android.app.ApplicationPackageManager.getApplicationInfo(ApplicationPackageManager.java:333) 12-17 06:01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: でmiui.core.ManifestParser.create(SourceFile:64) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: miui.core.SdkManager.start(SourceFile:186) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: java.lang.reflect.Method.invoke(Native Method) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: miui.external.a.abx() で 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: miui.external.a.attachBaseContext() で 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.Application で.attach(Application.java:193) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.Instrumentation.newApplication(Instrumentation.java:1009) 12-17 06:01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: でandroid.app.Instrumentation.newApplication(Instrumentation.java:993) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.LoadedApk.makeApplication(LoadedApk.java:800) 12-17 06 :01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.ActivityThread.handleBindApplication(ActivityThread.java:5471) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app で。 ActivityThread.-wrap2(ActivityThread.java) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.ActivityThread$H.handleMessage(ActivityThread.java:1584) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.os.Handler.dispatchMessage(Handler.java:102) 12-17 06:01: 29.334 8769 8769 W MIUI-BLOCK-MONITOR: でandroid.os.Looper.loop(Looper.java:163) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: android.app.ActivityThread.main(ActivityThread.java:6221) 12-17 06 :01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: java.lang.reflect.Method.invoke(Native Method) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: com.android.internal .os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 12-17 06:01:29.334 8769 8769 W MIUI-BLOCK-MONITOR: com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794 )
bindApplication 操作は 36 秒間実行されています。この場合、現時点ではシステムのステータスが楽観的ではない可能性が最も高くなります。次に、上記の分析を通じて、BootCompletedReceiver の onReceiver がメインスレッドを起動するだけでなく、Service の起動にも時間がかかります。時間がかかる場合は、Receiver の登録時に Handler を指定し、子スレッドで onReceiver を実行することも検討できます (方法はソースコードを参照してください) )
4. ANR 問題の分析ルーチン
- バグレポートを取得し、ANR を検索し、発生時間とプロセスを確認し、CPU 負荷に問題がないか確認します。
- 処理に応じてメインスレッドのトレースを検索してブロックされている箇所を見つけ、Binder呼び出しであればさらに相手の状況を確認し、時間のかかる操作であれば直接非同期に修正します。システムの実行が遅いのではないかと疑う場合は、binder_sample、dvm_lock、その他の情報を確認してください。次に、gcs が多いかどうか、lmk が頻繁にプロセスを強制終了するかどうかで、システムの健全性状態がわかります。
- ソースコードに基づいて問題を分析し解決する
この記事では、いくつかのケースと分析方法のみを記録します。基本的な考え方は、過去の期間にメインスレッドがブロックされた理由を調べることです。一般的に言えば、マスターするのは比較的簡単ですが、ANR のダンプ原則、システムが ANR を決定する方法、ANR の無効なトレースをどうするか、その他のより詳細な問題などの特定の原則にはまだ踏み込んでいません。 。ANR の問題は時々頭痛の種となるため、追跡が犯罪の最初の現場ではない可能性があります。一部の携帯電話メーカーは ANR の監視を強化しており、これによりより多くの情報が出力され、ANR 問題の分析効率が向上します。 Room で ANR の問題に取り組む学生は、職場でソース コードを読む経験があるため、より快適になることがわかりました。