【筆記】【從Android Guide溫習Android 二】ANR (Application Not Responding)

 

【筆記】【從Android Guide溫習Android 二】ANR (Application Not Responding)

官方文檔鏈接

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

ANR產生條件

  • KeyDispatchTimeout -- 按鍵或點擊屏幕5秒內沒反應java

  • BroadcastTimeout -- BroadcastReceiver沒有在10秒內結束android

  • ServiceTimeout -- Service20秒內沒有處理完成web

Time out

雖然和ANR有關,可是並非全部的Timeout都會引起ANR數據庫

由於解決辦法和ANR的相同甚至更多。網絡

能夠看一下ActivityManagerService或者ActivityStack的源碼,搜一下TIMEOUT,以下。app

```
// How long we wait until giving up on the last activity to pause.  This
// is short because it directly impacts the responsiveness of starting the
// next activity.
static final int PAUSE_TIMEOUT = 500;

// How long we wait for the activity to tell us it has stopped before
// giving up.  This is a good amount of time because we really need this
// from the application in order to get its saved state.
static final int STOP_TIMEOUT = 10*1000;

// How long we wait until giving up on an activity telling us it has
// finished destroying itself.
static final int DESTROY_TIMEOUT = 10*1000;

```

可見Acitivy中Pause,Stop,Destory對處理的時間也是有限制的。ide

如何避免

  • 耗時操做都放到工做線程(Worker Thread or Background Thread)中. 如網絡請求,數據庫讀寫,圖片縮放

可用特性

  • AsyncTaskoop

    注意其生命週期ui

  • Thread

    需設置

    Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND)。

    不要使用一下方法阻塞主線程

    Thread.wait() or Thread.sleep()
  • IntentService

    特別適用於BroadcastReceiver中的耗時操做。

用戶體驗

100到200ms之間,用戶會以爲軟件運行緩慢。

分析ANR

下面是ANR的log信息
01-10 10:23:04.838      561-586/? E/ActivityManager﹕ ANR in com.android.memorycleaner:remote, time=3677664
    Reason: Executing service com.android.memorycleaner/.service.PushService
    Load: 1.13 / 1.26 / 1.3
    CPU usage from 8110ms to 65ms ago:
    11% 701/com.android.systemui: 4.9% user + 6.5% kernel / faults: 108 minor
    4.7% 142/surfaceflinger: 1.6% user + 3% kernel
    4.5% 561/system_server: 2.7% user + 1.8% kernel / faults: 611 minor
    2.1% 4306/kworker/0:2: 0% user + 2.1% kernel
    1.9% 5087/com.tangyu.component: 1.2% user + 0.7% kernel / faults: 135 minor
    1.9% 5430/com.tencent.qqlive: 1.2% user + 0.7% kernel / faults: 450 minor
    1.1% 5545/com.android.vending: 0.6% user + 0.4% kernel / faults: 1854 minor
    1.7% 4598/kworker/0:3: 0% user + 1.7% kernel
    1.4% 891/com.htc.launcher: 1.2% user + 0.2% kernel / faults: 28 minor
    1.1% 140/netd: 0.9% user + 0.1% kernel / faults: 12 minor
    0.7% 152/akmd: 0% user + 0.7% kernel
    0.4% 153/ewtzmud: 0% user + 0.4% kernel
    0.4% 4538/kworker/u:3: 0% user + 0.4% kernel
    0.3% 3785/irq/210-host_sp: 0% user + 0.3% kernel
    0.2% 111/mmcqd/0: 0% user + 0.2% kernel
    0.2% 143/zygote: 0% user + 0.2% kernel / faults: 59 minor
    0.2% 456/adbd: 0% user + 0.2% kernel
    0.2% 1089/irq/340-wl12xx: 0% user + 0.2% kernel
    0.1% 5143/com.android.memorycleaner: 0% user + 0% kernel / faults: 46 minor
    0.1% 145/mediaserver: 0% user + 0.1% kernel
    0.1% 507/logcat: 0% user + 0.1% kernel
    0% 1110/wpa_supplicant: 0% user + 0% kernel
    0.1% 3786/irq/214-host_sp: 0% user + 0.1% kernel
    0% 5487/com.htc.dnatransfer: 0% user + 0% kernel / faults: 2 minor
    0.1% 5616/com.google.android.gm: 0% user + 0.1% kernel
    0.1% 5725/com.android.ss: 0.1% user + 0% kernel / faults: 20 minor
    +0% 5747/com.htc.calendar: 0% user + 0% kernel
    18% TOTAL: 8.2% user + 9.8% kernel + 0.4% iowait + 0% irq + 0.1% softirq
    CPU usage from 1435ms to 1956ms later:
    5.7% 561/system_server: 3.8% user + 1.9% kernel / faults: 2 minor
    3.8% 586/ActivityManager: 1.9% user + 1.9% kernel
    1.2% 142/surfaceflinger: 0% user + 1.2% kernel
    1.2% 459/EventThread: 0% user + 1.2% kernel
    1.3% 701/com.android.systemui: 1.3% user + 0% kernel
    2.7% 701/ndroid.systemui: 1.3% user + 1.3% kernel
    3.8% TOTAL: 1.9% user + 1.9% kernel
重點看一下這幾點
  1. 緣由:

    Reason: Executing service com.android.memorycleaner/.service.PushService

    啊,com.android.memorycleaner/.service.PushService這個東西引起了ANR

  2. Total信息

    • ANR發生前

      18% TOTAL: 8.2% user + 9.8% kernel + 0.4% iowait + 0% irq + 0.1% softirq

    • ANR發生後

      3.8% TOTAL: 1.9% user + 1.9% kernel

能夠抽出幾個關鍵詞:
  • CPU

    • 若CPU彪到了100%,有多是CPU飢餓致使了ANR

    • 若CPU很少。說明主線程被BLOCK了。

    當前爲18%.

  • PID(進程號) + Package-name(包名)

    方便確認是你程序的那個進程異常。

  • IOwait

    若IOWait高,說明在主線程有讀寫操做致使ANR。

  • 看上去數值沒異常

    正如此例子。

    這時候就多是另外一種狀況引發的ANR -- 主線程中有網絡通信

    下面就祭上咱們的神器 Trace文件

Traces.txt
  • 此文件位於設備中的 /data/anr/traces.txt

  • vi traces.txt 查看文件內容。內容有不少。咱們只看開始就能夠。以下。

1                                                                                                                                                  
   2 
   3 ----- pid 13359 at 2014-01-10 12:33:03 -----
   4 Cmd line: com.android.memorycleaner:remote
   5 
   6 DALVIK THREADS:
   7 (mutexes: tll=0 tsl=0 tscl=0 ghl=0)
   8 
   9 "main" prio=5 tid=1 NATIVE
  10   | group="main" sCount=1 dsCount=0 obj=0x41a42e50 self=0x400f6010
  11   | sysTid=13359 nice=0 sched=0/0 cgrp=apps handle=1074345436
  12   | state=S schedstat=( 626677000 787645000 1599 ) utm=32 stm=30 core=3
  13   #00  pc 000180d0  /system/lib/libc.so (poll+12)
  14   #01  pc 00020d73  /system/lib/libjavacore.so
  15   #02  pc 0001e690  /system/lib/libdvm.so (dvmPlatformInvoke+112)
  16   #03  pc 0005100f  /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+426)
  17   #04  pc 00027aa0  /system/lib/libdvm.so
  18   #05  pc 0002ce84  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+232)
  19   #06  pc 000674bf  /system/lib/libdvm.so (dvmInvokeMethod(Object*, Method const*, ArrayObject*, ArrayObject*, ClassObject*, bool)+374)
  20   #07  pc 0007066f  /system/lib/libdvm.so
  21   #08  pc 00027aa0  /system/lib/libdvm.so
  22   #09  pc 0002ce84  /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+232)
  23   #10  pc 000671a1  /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+272)
  24   #11  pc 0004d2d7  /system/lib/libdvm.so
  25   #12  pc 0004d391  /system/lib/libandroid_runtime.so
  26   #13  pc 0004e22d  /system/lib/libandroid_runtime.so (android::AndroidRuntime::start(char const*, char const*)+540)
  27   #14  pc 00000e67  /system/bin/app_process
  28   #15  pc 000128b3  /system/lib/libc.so (__libc_init+38)
  29   #16  pc 00000b74  /system/bin/app_process
  30   at libcore.io.Posix.poll(Native Method)
  31   at libcore.io.BlockGuardOs.poll(BlockGuardOs.java:-1)
  32   at libcore.io.IoBridge.isConnected(IoBridge.java:-1)
  33   at libcore.io.IoBridge.connectErrno(IoBridge.java:-1)
  34   at libcore.io.IoBridge.connect(IoBridge.java:-1)
  35   at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:-1)
  36   at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:-1)
  37   at java.net.Socket.connect(Socket.java:-1)
  38   at com.b.a.a.a.<init>((null):-1)
  39   at com.b.a.a.b.a((null):-1)
  40   at com.b.a.e.a((null):-1)
  41   at com.b.a.h.a((null):-1)
  42   at com.b.a.h.a((null):-1)
  43   at com.b.a.k.a((null):-1)
  44   at com.b.a.k.a((null):-1)
  45   at com.android.memorycleaner.service.c.<init>((null):-1)
  46   at com.android.memorycleaner.service.PushService.m((null):-1)
  47   at com.android.memorycleaner.service.PushService.q((null):-1)
  48   at com.android.memorycleaner.service.PushService.onStart((null):-1)
  49   at android.app.Service.onStartCommand(Service.java:-1)
  50   at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:-1)
  51   at android.app.ActivityThread.access$1900(ActivityThread.java:-1)
  52   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:-1)
  53   at android.os.Handler.dispatchMessage(Handler.java:-1)
  54   at android.os.Looper.loop(Looper.java:-1)
  55   at android.app.ActivityThread.main(ActivityThread.java:-1)
  56   at java.lang.reflect.Method.invokeNative(Native Method)
  57   at java.lang.reflect.Method.invoke(Method.java:-1)
  58   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:-1)
  59   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:-1)
  60   at dalvik.system.NativeStart.main(Native Method)

這部份內容展示的是引起ANR的線程的調用堆棧信息。有了他咱們還怕什麼!

顯而易見

com.android.memorycleaner.service.c.((null):-1) 之上有不少包名的含義直指網絡相關。

雖然看不到com.android.memorycleaner.service 的源碼。咱們能夠推斷出是因爲網絡請求致使的ANR。

總結

  • 耗時工做統統放到工做線程去作是避免ANR的萬金油

  • 出現ANR也不用怕。簡單分析就能推斷出問題所在。

連接

http://www.360doc.com/content/12/0226/15/7635_189765894.shtml

https://dl.google.com/googleio/2010/android-writing-zippy-android-apps.pdf

相關文章
相關標籤/搜索