精华内容
参与话题
问答
  • 浅谈ANR及log分析ANR

    万次阅读 多人点赞 2011-10-30 14:54:03
    一:什么是ANR ANR:Application Not Responding,即应用无响应 二:ANR的类型 ANR一般有三种类型: 1:KeyDispatchTimeout(5 seconds) --主要类型 按键或触摸事件在特定时间内无响应 2:...
    
    

    一:什么是ANR

    ANR:Application Not Responding,即应用无响应

    二:ANR的类型

    ANR一般有三种类型:

    1KeyDispatchTimeout(5 seconds) --主要类型

    按键或触摸事件在特定时间内无响应

    2BroadcastTimeout(10 seconds)

    BroadcastReceiver在特定时间内无法处理完成

    3ServiceTimeout(20 seconds) --小概率类型

    Service在特定的时间内无法处理完成

    三:KeyDispatchTimeout

    Akey or touch event was not dispatched within the specified time(按键或触摸事件在特定时间内无响应)

    具体的超时时间的定义在framework下的

    ActivityManagerService.java

    //How long we wait until we timeout on key dispatching.

    staticfinal int KEY_DISPATCHING_TIMEOUT = 5*1000

    四:为什么会超时呢?

    超时时间的计数一般是从按键分发给app开始。超时的原因一般有两种

    (1)当前的事件没有机会得到处理(即UI线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)

    (2)当前的事件正在处理,但没有及时完成

    五:如何避免KeyDispatchTimeout

    1UI线程尽量只做跟UI相关的工作

    2:耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理

    3:尽量用Handler来处理UIthread和别的thread之间的交互


    六:UI线程

    说了那么多的UI线程,那么哪些属于UI线程呢?

    UI线程主要包括如下:

    1. Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc

    2. AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc

    3. Mainthread handler: handleMessage(), post*(runnable r), etc

      :如何去分析ANR

      先看个LOG:

      04-01 13:12:11.572 I/InputDispatcher( 220): Application is not responding:Window{2b263310com.android.email/com.android.email.activity.SplitScreenActivitypaused=false}.  5009.8ms since event, 5009.5ms since waitstarted

      04-0113:12:11.572 I/WindowManager( 220): Input event dispatching timedout sending tocom.android.email/com.android.email.activity.SplitScreenActivity

      04-01 13:12:14.123 I/Process(  220): Sending signal. PID: 21404 SIG: 3---发生ANR的时间和生成trace.txt的时间

      04-01 13:12:14.123 I/dalvikvm(21404):threadid=4: reacting to signal 3 

      ……

      04-0113:12:15.872 E/ActivityManager(  220): ANR in com.android.email(com.android.email/.activity.SplitScreenActivity)

      04-0113:12:15.872 E/ActivityManager(  220): Reason:keyDispatchingTimedOut

      04-0113:12:15.872 E/ActivityManager(  220): Load: 8.68 / 8.37 / 8.53

      04-0113:12:15.872 E/ActivityManager(  220): CPUusage from 4361ms to 699ms ago ----CPUANR发生前的使用情况


      04-0113:12:15.872 E/ActivityManager(  220):   5.5%21404/com.android.email: 1.3% user + 4.1% kernel / faults: 10 minor

      04-0113:12:15.872 E/ActivityManager(  220):   4.3%220/system_server: 2.7% user + 1.5% kernel / faults: 11 minor 2 major

      04-0113:12:15.872 E/ActivityManager(  220):   0.9%52/spi_qsd.0: 0% user + 0.9% kernel

      04-0113:12:15.872 E/ActivityManager(  220):   0.5%65/irq/170-cyttsp-: 0% user + 0.5% kernel

      04-0113:12:15.872 E/ActivityManager(  220):   0.5%296/com.android.systemui: 0.5% user + 0% kernel

      04-0113:12:15.872 E/ActivityManager(  220): 100%TOTAL: 4.8% user + 7.6% kernel + 87% iowait

      04-0113:12:15.872 E/ActivityManager(  220): CPUusage from 3697ms to 4223ms later:-- ANRCPU的使用量

      04-0113:12:15.872 E/ActivityManager(  220):   25%21404/com.android.email: 25% user + 0% kernel / faults: 191 minor

      04-0113:12:15.872 E/ActivityManager(  220):    16% 21603/__eas(par.hakan: 16% user + 0% kernel

      04-0113:12:15.872 E/ActivityManager(  220):    7.2% 21406/GC: 7.2% user + 0% kernel

      04-0113:12:15.872 E/ActivityManager(  220):    1.8% 21409/Compiler: 1.8% user + 0% kernel

      04-0113:12:15.872 E/ActivityManager(  220):   5.5%220/system_server: 0% user + 5.5% kernel / faults: 1 minor

      04-0113:12:15.872 E/ActivityManager(  220):    5.5% 263/InputDispatcher: 0% user + 5.5% kernel

      04-0113:12:15.872 E/ActivityManager(  220): 32%TOTAL: 28% user + 3.7% kernel


      LOG可以看出ANR的类型,CPU的使用情况,如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR

      如果CPU使用量很少,说明主线程被BLOCK

      如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的

      除了看LOG,解决ANR还得需要trace.txt文件,

      如何获取呢?可以用如下命令获取

      1. $chmod 777 /data/anr

      2. $rm /data/anr/traces.txt

      3. $ps

      4. $kill -3 PID

      5. adbpull data/anr/traces.txt ./mytraces.txt

      trace.txt文件,看到最多的是如下的信息:

      -----pid 21404 at 2011-04-01 13:12:14 -----  
      Cmdline: com.android.email

      DALVIK THREADS:
      (mutexes: tll=0tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
      "main" prio=5 tid=1NATIVE
        | group="main" sCount=1 dsCount=0obj=0x2aad2248 self=0xcf70
        | sysTid=21404 nice=0 sched=0/0cgrp=[fopen-error:2] handle=1876218976
        atandroid.os.MessageQueue.nativePollOnce(Native Method)
        atandroid.os.MessageQueue.next(MessageQueue.java:119)
        atandroid.os.Looper.loop(Looper.java:110
      )
       at android.app.ActivityThread.main(ActivityThread.java:3688)
       at java.lang.reflect.Method.invokeNative(Native Method)
        atjava.lang.reflect.Method.invoke(Method.java:507)
        atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
       at dalvik.system.NativeStart.main(Native Method)

      说明主线程在等待下条消息进入消息队列

      八:Thread状态

      ThreadState (defined at “dalvik/vm/thread.h “)

      THREAD_UNDEFINED = -1, /* makes enum compatible with int32_t */

      THREAD_ZOMBIE = 0, /* TERMINATED */

      THREAD_RUNNING = 1, /* RUNNABLE or running now */

      THREAD_TIMED_WAIT = 2, /* TIMED_WAITING in Object.wait() */

      THREAD_MONITOR = 3, /* BLOCKED on a monitor */

      THREAD_WAIT = 4, /* WAITING in Object.wait() */

      THREAD_INITIALIZING= 5, /* allocated, not yet running */

      THREAD_STARTING = 6, /* started, not yet on thread list */

      THREAD_NATIVE = 7, /* off in a JNI native method */

      THREAD_VMWAIT = 8, /* waiting on a VM resource */

      THREAD_SUSPENDED = 9, /* suspended, usually by GC or debugger */


      九:如何调查并解决ANR

      1:首先分析log

      2: trace.txt文件查看调用stack.

      3: 看代码

      4:仔细查看ANR的成因(iowait?block?memoryleak?


    4. other

      十:案例

      案例1关键词:ContentResolver in AsyncTask onPostExecute, high iowait

      Process:com.android.email
      Activity:com.android.email/.activity.MessageView
      Subject:keyDispatchingTimedOut
      CPU usage from 2550ms to -2814ms ago:
      5%187/system_server: 3.5% user + 1.4% kernel / faults: 86 minor 20major
      4.4% 1134/com.android.email: 0.7% user + 3.7% kernel /faults: 38 minor 19 major
      4% 372/com.android.eventstream: 0.7%user + 3.3% kernel / faults: 6 minor
      1.1% 272/com.android.phone:0.9% user + 0.1% kernel / faults: 33 minor
      0.9%252/com.android.systemui: 0.9% user + 0% kernel
      0%409/com.android.eventstream.telephonyplugin: 0% user + 0% kernel /faults: 2 minor
      0.1% 632/com.android.devicemonitor: 0.1% user + 0%kernel
      100%TOTAL: 6.9% user + 8.2% kernel + 84%iowait


      -----pid 1134 at 2010-12-17 17:46:51 -----
      Cmd line:com.android.email

      DALVIK THREADS:
      (mutexes: tll=0 tsl=0tscl=0 ghl=0 hwl=0 hwll=0)
      "main" prio=5 tid=1 WAIT
      |group="main" sCount=1 dsCount=0 obj=0x2aaca180self=0xcf20
      | sysTid=1134 nice=0 sched=0/0 cgrp=[fopen-error:2]handle=1876218976
      at java.lang.Object.wait(Native Method)
      -waiting on <0x2aaca218> (a java.lang.VMThread)
      atjava.lang.Thread.parkFor(Thread.java:1424)
      atjava.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
      atsun.misc.Unsafe.park(Unsafe.java:337)
      atjava.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
      atjava.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:808)
      atjava.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:841)
      atjava.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1171)
      atjava.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:200)
      atjava.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:261)
      atandroid.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:378)
      atandroid.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:222)
      atandroid.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
      atandroid.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1356)
      atandroid.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1235)
      atandroid.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1189)
      atandroid.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1271)
      atcom.android.email.provider.EmailProvider.query(EmailProvider.java:1098)
      atandroid.content.ContentProvider$Transport.query(ContentProvider.java:187)
      atandroid.content.
      ContentResolver.query(ContentResolver.java:268)
      atcom.android.email.provider.EmailContent$Message.restoreMessageWithId(EmailContent.java:648)
      atcom.android.email.Controller.setMessageRead(Controller.java:658)
      atcom.android.email.activity.MessageView.onMarkAsRead(MessageView.java:700)
      atcom.android.email.activity.MessageView.access$2500(MessageView.java:98)
      at
      com.android.email.activity.MessageView$LoadBodyTask.onPostExecute(MessageView.java:1290)
      atcom.android.email.activity.MessageView$LoadBodyTask.onPostExecute(MessageView.java:1255)
      atandroid.os.AsyncTask.finish(AsyncTask.java:417)
      atandroid.os.AsyncTask.access$300(AsyncTask.java:127)
      at
      android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
      atandroid.os.Handler.dispatchMessage(Handler.java:99)
      atandroid.os.Looper.loop(Looper.java:123)
      atandroid.app.ActivityThread.main(ActivityThread.java:3652)
      atjava.lang.reflect.Method.invokeNative(Native Method)
      atjava.lang.reflect.Method.invoke(Method.java:507)
      atcom.android.internal.os.ZygoteIn

      原因:IOWait很高,说明当前系统在忙于I/O,因此数据库操作被阻塞

      原来:

              finalMessagemessage =Message.restoreMessageWithId(mProviderContext,messageId);

              if(message==null){

                 return;

              }

              Accountaccount =Account.restoreAccountWithId(mProviderContext,message.mAccountKey);

              if(account==null){

                 return;//isMessagingController returns false for null, but let's make itclear.

              }

              if(isMessagingController(account)){

                 newThread(){

                     @Override

                     publicvoidrun(){

                        mLegacyController.processPendingActions(message.mAccountKey);

                     }

                 }.start();

              }


      解决后:

      newThread() {

              finalMessagemessage =Message.restoreMessageWithId(mProviderContext,messageId);

              if(message==null){

                 return;

              }

              Accountaccount =Account.restoreAccountWithId(mProviderContext,message.mAccountKey);

              if(account==null){

                 return;//isMessagingController returns false for null, but let's make itclear.

              }

              if(isMessagingController(account)) {

                        mLegacyController.processPendingActions(message.mAccountKey);

                    

                 }


      }.start();

      关于AsyncTask:http://developer.android.com/reference/android/os/AsyncTask.html


      案例2关键词:UI线程进行网络数据的读写

      ANRin process: com.android.mediascape:PhotoViewer (last incom.android.mediascape:PhotoViewer)
      Annotation:keyDispatchingTimedOut
      CPU usage:
      Load: 6.74 / 6.89 / 6.12
      CPUusage from 8254ms to 3224ms ago:
      ovider.webmedia: 4% = 4% user +0% kernel / faults: 68 minor
      system_server: 2% = 1% user + 0%kernel / faults: 18 minor
      re-initialized>: 0% = 0% user + 0%kernel / faults: 50 minor
      events/0: 0% = 0% user + 0%kernel
      TOTAL:7% = 6% user + 1% kernel

      DALVIKTHREADS:
      ""main"" prio=5 tid=3 NATIVE
      |group=""main"" sCount=1 dsCount=0 s=Yobj=0x4001b240 self=0xbda8
      | sysTid=2579 nice=0 sched=0/0cgrp=unknown handle=-1343993184
      atorg.apache.harmony.luni.platform.OSNetworkSystem.receiveStreamImpl(NativeMethod)
      atorg.apache.harmony.luni.platform.
      OSNetworkSystem.receiveStream(OSNetworkSystem.java:478)
      atorg.apache.harmony.luni.net.PlainSocketImpl.read(PlainSocketImpl.java:565)
      atorg.apache.harmony.luni.net.SocketInputStream.read(SocketInputStream.java:87)
      atorg.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnection$LimitedInputStream.read(HttpURLConnection.java:303)
      atjava.io.InputStream.read(InputStream.java:133)
      atjava.io.BufferedInputStream.fillbuf(BufferedInputStream.java:157)
      atjava.io.BufferedInputStream.read(BufferedInputStream.java:346)
      atandroid.graphics.BitmapFactory.nativeDecodeStream(Native Method)
      atandroid.graphics.
      BitmapFactory.decodeStream(BitmapFactory.java:459)
      atcom.android.mediascape.activity.PhotoViewerActivity.
      getPreviewImage(PhotoViewerActivity.java:4465)
      atcom.android.mediascape.activity.PhotoViewerActivity.
      dispPreview(PhotoViewerActivity.java:4406)
      atcom.android.mediascape.activity.PhotoViewerActivity.access$6500(PhotoViewerActivity.java:125)

      atcom.android.mediascape.activity.PhotoViewerActivity$33$1.run(PhotoViewerActivity.java:4558)
      atandroid.os.Handler.handleCallback(Handler.java:587)
      atandroid.os.Handler.dispatchMessage(Handler.java:92)
      atandroid.os.Looper.loop(Looper.java:123)
      atandroid.app.ActivityThread.main(ActivityThread.java:4370)
      atjava.lang.reflect.Method.invokeNative(Native Method)
      atjava.lang.reflect.Method.invoke(Method.java:521)
      atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
      atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
      atdalvik.system.NativeStart.main(Native Method)

      关于网络连接,再设计的时候可以设置个timeout的时间或者放入独立的线程来处理。

      关于Handler的问题,可以参考:http://developer.android.com/reference/android/os/Handler.html

      案例3

      关键词:Memoryleak/Thread leak

      11-1621:41:42.560 I/ActivityManager( 1190): ANR in process:android.process.acore (last in android.process.acore)
      11-1621:41:42.560 I/ActivityManager( 1190): Annotation:keyDispatchingTimedOut
      11-16 21:41:42.560 I/ActivityManager(1190): CPU usage:
      11-16 21:41:42.560 I/ActivityManager( 1190):Load: 11.5 / 11.1 / 11.09
      11-16 21:41:42.560 I/ActivityManager(1190): CPU usage from 9046ms to 4018ms ago:
      11-16 21:41:42.560I/ActivityManager( 1190): 
      d.process.acore:98%= 97% user + 0% kernel / faults: 1134 minor
      11-16 21:41:42.560I/ActivityManager( 1190): system_server: 0% = 0% user + 0% kernel /faults: 1 minor
      11-16 21:41:42.560 I/ActivityManager( 1190): adbd:0% = 0% user + 0% kernel
      11-16 21:41:42.560 I/ActivityManager(1190): logcat: 0% = 0% user + 0% kernel
      11-16 21:41:42.560I/ActivityManager( 1190): 
      TOTAL:100% = 98% user + 1% kernel

      Cmdline: android.process.acore

      DALVIK THREADS:
      "main"prio=5 tid=3 
      VMWAIT
      |group="main" sCount=1 dsCount=0 s=N obj=0x40026240self=0xbda8
      | sysTid=1815 nice=0 sched=0/0 cgrp=unknownhandle=-1344001376
      atdalvik.system.
      VMRuntime.trackExternalAllocation(NativeMethod)
      atandroid.graphics.Bitmap.nativeCreate(Native Method)
      atandroid.graphics.
      Bitmap.createBitmap(Bitmap.java:468)
      atandroid.view.View.buildDrawingCache(View.java:6324)
      atandroid.view.View.getDrawingCache(View.java:6178)
      atandroid.view.ViewGroup.drawChild(ViewGroup.java:1541)
      ……
      atcom.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1830)
      atandroid.view.ViewRoot.draw(ViewRoot.java:1349)
      atandroid.view.ViewRoot.performTraversals(ViewRoot.java:1114)
      atandroid.view.ViewRoot.handleMessage(ViewRoot.java:1633)
      atandroid.os.Handler.dispatchMessage(Handler.java:99)
      atandroid.os.Looper.loop(Looper.java:123)
      atandroid.app.ActivityThread.main(ActivityThread.java:4370)
      atjava.lang.reflect.Method.invokeNative(Native Method)
      atjava.lang.reflect.Method.invoke(Method.java:521)
      atcom.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
      atcom.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
      atdalvik.system.NativeStart.main(Native Method)

      "Thread-408"prio=5 tid=329 WAIT 
      |group="main" sCount=1 dsCount=0 s=N obj=0x46910d40self=0xcd0548
      | sysTid=10602 nice=0 sched=0/0 cgrp=unknownhandle=15470792
      at java.lang.Object.wait(Native Method)
      -waiting on <0x468cd420> (a java.lang.Object)
      atjava.lang.Object.wait(Object.java:288)
      atcom.android.dialer.CallLogContentHelper$UiUpdaterExecutor$1.run(CallLogContentHelper.java:289)
      atjava.lang.Thread.run(Thread.java:1096)

      分析:

      atdalvik.system.VMRuntime.trackExternalAllocation(NativeMethod)内存不足导致block在创建bitmap

      **MEMINFO in pid 1360 [android.process.acore] **
      native dalvik other total
      size: 17036 
      23111 N/A 40147
      allocated: 16484 20675 N/A 37159
      free: 296 2436 N/A 2732

      解决:如果机器的内存族,可以修改虚拟机的内存为36M或更大,不过最好是复查代码,查看哪些内存没有释放


    展开全文
  • ANR问题全解析

    千次阅读 2019-04-29 18:55:09
    大部分做安卓的小伙伴相信对于ANR一定不陌生,相比于发生应用程序崩溃,发生ANR更加让人头大,主要原因是崩溃发生的时候会在Logcat中打印出发生异常的位置,开发人员很容易就能定位到崩溃并解决,显然ANR没那么轻松...

    大部分做安卓的小伙伴相信对于ANR一定不陌生,相比于发生应用程序崩溃,发生ANR更加让人头大,主要原因是崩溃发生的时候会在Logcat中打印出发生异常的位置,开发人员很容易就能定位到崩溃并解决,显然ANR没那么轻松;但是我们大可不必这么忧伤,因为绝大部分ANR都是很容易解决的,只是我们没找到方法而已;

    首先要搞定ANR就要对他有一个根本性的认识,和我们了解任何事物一样,只有抓住了事物之根本,才能在应对各种各样复杂的场景时保持镇定,运筹帷幄;

    认识问题

    那什么是ANR呢?我总结过来说就是Google为了让应用足够快的响应用户引入的一套机制,当主线程的UI绘制变慢的时候就可能导致ANR异常;不过这些基础知识对于各位看官来说都是小儿科了,我们就直奔主题,是什么导致应用程序出现ANR异常,而我们又应该怎么灵巧应对这些异常呢?

    我这里给出一个官方的解释,其实我很鼓励大家在遇到问题的时候先看官方文档,因为官方的解释最能抓住问题的根本,与其说这是一种方法,倒不如说是一种解决问题的思维方式;
    在这里插入图片描述
    官方标出了重点,就是不要在主线程上做耗时操作,不过我们在解Bug的时候发现远比这一句话来得复杂,及时我们尽量不让主线程执行耗时操作,也会遇到一些头疼的ANR场景,这个是我们今天要解决的重点;

    我简单的把这些场景氛围3类:

    1. KeyDispatchTimeout(主要类型)
      按键或触摸事件在特定时间内无响应,谷歌default 5s,MTK平台上是8s;其实这个很好理解,第一种是和用户交互的时候出现的,能和用户直接交互的界面就是运行在主线程上,当程序无法响应用户的交互事件,自然会抛出来ANR;
    2. BroadcastTimeout(10s)
      BroadcastReceiver在特定时间内无法处理完成,因为Broadcast是跑在主线程上的,而且Broadcast的生命周期只有10s,10s没有做完就会被安卓系统认为出现了ANR异常;
    3. ServiceTimeout(20s) --小概率类型
      Service在特定的时间内无法处理完成,Service是跑在主线程上的,这种情况出现的不多,我相信大部分开发人员能规避这种情景;

    解决问题

    我想在这里给大家一个解决这类问题的一般思路,基本上顺着这个方法能解决绝大部分的ANR问题;

    第一步:获取ANR日志

    ANR产生时, 系统会生成一个traces.txt的文件放在/data/anr/下.,这个文件里面保存了产生ANR的相关日志,可以通过adb命令将其导出到本地:

    $adb pull data/anr/traces.txt .
    

    获取日志有一点需要注意,发生ANR后,不要选择结束进程,因为这样AMS会kill掉该进程,有些信息会打印不出来(比如MTK平台上会生成db.XX.ANR,写入到aee_exp文件夹下需要时间),最好是ANR发生后等两三分钟左右,再获取日志;

    有些时候我们仅仅通过traces.txt无法准确定位到ANR产生的原因,这个时候还需要一些日志辅助定位,以MTK为例,需要如下日志信息:
    1.aee_exp文件夹(MTK日志目录下,发生ANR会生成)
    2.MTK目录下的mobilelog文件夹

    这里的aee_exp文件夹一般都是需要的, 对DB进行dump解析,得到ANR发生时场景信息,比如主线程callstack,CPU,memory等,在分析比较难的ANR问题时很关键。

    第二步:分析日志

    找到日志后,我们需要通过日志快速定位到问题,我解决问题的思路是从我最常见到的问题入手,尽可能少的通过关键资料得到问题结果,如果不能再复杂化;这样做是为了节省时间,我可不想每次分析一个ANR就分析一遍堆栈占用,Cpu线程等等,这样很容易让人搞不清楚主次而浪费时间;

    下面是我分析日志的常规思路,当然如果你有更好的方法欢迎指正;

    第一类:能直接从traces.txt .看出原因的ANR

    在这里插入图片描述
    你看,人家说的很明白了,界面都没出来,点了肯定是没办法响应的,这种情况下一般是在Application或者Activity创建的时候做了耗时操作,因此规避方法也很简单就是尽可能把耗时操作挪到子线程去做;

    第二类 主线程做了耗时操作

    虽然第一类也是属于这种,但是区别在于这一类问题一般发生在应用运行过程中,这种情况是ANR类型问题里遇到最多的,比如网络访问,访问数据库之类的,都很容易造成主线程堵塞;
    我解决这类问题的时候不是直接看tractView.txt,因为android studio提供了一个非常好的性能分析工具供我们跟踪这个问题,我们只需要打开android studio的性能分析页面:
    在这里插入图片描述
    进入到Cpu页面,第一个线程就是主线程,我们只要看主线程上cpu的占用(绿色块)就知道在什么时候要发生ANR了,因为发生ANR的时候,主线程会有很大块的绿色占用,我们使用录制工具,录制这段时间的cpu占用,就可以很快定位到问题,这一类的教程很多,我这里不再赘述;

    第三类:死锁导致ANR

    这类问题相比前两类要麻烦一些,很多初级开发是不知道的;
    首先我们要确定ANR的发生时因为用户点击还是自己就发生了,因为如果测试人员没有点击就发生了ANR,那很可能是出现了死锁,死锁在日志上的表现是很直接的,因为我们知道死锁导致的ANR的根源是是因为一个线程持有了锁主线程在等待这个线程释放锁;当等待时间一场,必然发生ANR;

    这种情况下我们直接在日志里面找下面这些字样:
    在这里插入图片描述
    大家看我标红的位置,一看就知道是这里主线程阻塞了,原因是在等待45号线程持有的锁释放;通常这个时候还会在上面打印出来是发生在哪一行代码中,这个时候我们定位到对应的代码,再去解决这个问题就相当容易;

    第四类:卡IO

    这种情况一般是和文件操作相关,判断是否是这种情况,可以看mainlog中搜索关键字"ANR in",看这段信息的最下边,比如下面的信息
    ANRManager: 100% TOTAL: 2% user + 2.1% kernel + 95% iowait + 0.1% softirq
    很明显,IO占比很高,这个时候就需要查看trace日志看当时的callstack,或者在这段ANR点往前看0~4s,看看当时做的什么文件操作,这种场景有遇到过,常见解决方法是对耗时文件操作采取异步操作;

    第五类:Binder线程池被占满

    这一类问题出现的很少见,但是少不代表没有;
    系统对每个process最多分配15个binder线程,这个是谷歌的设计(/frameworks/native/libs/binder/ProcessState.cpp)
    如果另一个process发送太多重复binder请求,那么就会导致接收端binder线程被占满,从而处理不了其它的binder请求
    这本身就是系统的一个限制,如果应用未按照系统的要求来实现对应逻辑,那么就会造成问题。
    而系统端是不会(也不建议)通过修改系统行为来兼容应用逻辑,否则更容易造成其它根据系统需求正常编写的应用反而出现不可预料的问题。
    判断Binder是否用完,可以在trace中搜索关键字"binder_f",如果搜索到则表示已经用完,然后就要找log其他地方看是谁一直在消耗binder或者是有死锁发生
    之前有遇到过压力测试手电筒应用,出现BInder线程池被占满情况,解决的思路就是降低极短时间内大量Binder请求的发生,修复的手法是发送BInder请求的函数中做时间差过滤,限定在500ms内最多执行一次;

    第六类:主线程Binder调用等待超时

    一般是上面的我发现都不好使了,我才会使用这种方案,大家看一下下面这段:
    在这里插入图片描述
    很明显当时在做Binder通信,并没有waiting to lock等代表死锁的字样,那么说明这个案例即有可能是在等Binder对端响应,我们知道Binder通信对于发起方来说是阻塞等待响应,只有有了返回结果后才会继续执行下去
    所以,如上这个案例中需要找到对端是哪个进程,这个进程当时在做什么,这时候就需要找到anr文件夹下另外一个文件binderinfo,这里需要找到与我们发起方进程1461通信的是哪个进程;

    在这里插入图片描述

    可以看到是1666号这个进程,再回到trace中看下,这个进程当时在做什么

    在这里插入图片描述

    可以看到当时对端在做消息的读取,也就是说这里出了问题,很明显这里我们无法修改,我们这个问题在于主线程执行了Binder请求,对端迟迟未返回便很容易出现这个问题,当前做法异步中执行;

    展开全文
  • ANR解决思路

    2019-05-08 18:57:33
    本文案例主要源于项目上实际遇到的问题,希望通过梳理之后能够对ANR问题能够快速定位,减少排查时间,同时在遇到棘手问题,能够更加从容。 先说下三种常见类型 1:KeyDispatchTimeout(谷歌default 5s(input),MTK...

    From

    本文案例主要源于项目上实际遇到的问题,希望通过梳理之后能够对ANR问题能够快速定位,减少排查时间,同时在遇到棘手问题,能够更加从容。

    先说下三种常见类型
    1:KeyDispatchTimeout(谷歌default 5s(input),MTK平台上是8s) --主要类型
    按键或触摸事件在特定时间内无响应
    2:BroadcastTimeout(前台:10s  后台:60s)
    BroadcastReceiver在特定时间内无法处理完成
    3:ServiceTimeout(前台:20s 后台:200s) --小概率类型
    Service在特定的时间内无法处理完成

    4:ContentProvider:(10s)

    一般解决步骤

    Step1:日志获取&注意事项

    获取日志有一点需要注意,发生ANR后,不要选择结束进程,因为这样AMS会kill掉该进程,有些信息会打印不出来(比如MTK平台上会生成db.XX.ANR,写入到aee_exp文件夹下需要时间),最好是ANR发生后等两三分钟左右,再获取日志

    一般需要data/anr下生成的trace文件以及手机系统日志(一般只需要mobile文件夹)

    以MTK为例,需要如下日志信息:

    1.aee_exp文件夹(MTK日志目录下,发生ANR会生成)
    2.MTK目录下的mobilelog文件夹

    这里的aee_exp文件夹一般都是需要的, 对DB进行dump解析,得到ANR发生时场景信息,比如主线程callstack,CPU,memory等,在分析问题根因时很关键。

    Step2:日志分析一般步骤
    Step2.1 确认时间点(非必需)
    mobilelog文件夹下的events_log,搜索关键字"am_anr",这一步用于确认ANR时间点,可以搜索到类似如下信息

    04-29 10:00:57.240 1267 1341 I am_anr : [0,6073,com.android.dialer,952745541,Input dispatching timed out

    比如上面这行表示ANR类型为Input dispatching timed out, 这种anr的原因的是在viewrootimpl分发事件时,并没有找到focuswindow导致的

    这一步确认时间点在:10:00:57,进程号:6073

    Step2: 查看ANR时的CPU以及IO率(可选)

    这一步一般来说能基本定位是什么造成了ANR,是IO高还是CPU高,如两者都不是,需进入第三步trace日志分析环节 查看mobilelog文件夹下的main_log,搜索关键字"ANR in",可以看到当时的CPU以及IO率,这一个环节一般来讲主要是看发生ANR时的CPU使用情况,CPU是否吃紧,

    还有需要注意iowait的占有率,如果占比比较高,则排查的方向要倾向与读取文件操作有关的信息,可以看trace日志中有没有一些读取文件或者操作SD卡的动作

    Step3:分析ANR时的堆栈(必需,最重要的环节)
    ANR发生后会在data/anr下生成trace.txt,这份trace务必要与moile日志匹配,一般来讲直接先看tid=1的堆栈即对应主线程,因为ANR都是主线程执行超时导致

    关于trace日志的分析是ANR问题分析最重要的一个环节,下面将列出平时项目中遇到的ANR案例类型

    ANR常见类型归纳

    1.主线程Binder调用等待超时

    比如下面的这段

    1_binder等待超时.png

    很明显当时在做Binder通信,并没有waiting to lock等代表死锁的字样,那么说明这个案例即有可能是在等Binder对端响应,我们知道Binder通信对于发起方来说是默认是阻塞等待响应,只有有了返回结果后才会继续执行下去,当然了可以给接口设置oneway声明,这样的话binder请求就是异步请求,这里不多说

    所以,如上这个案例中需要找到对端是哪个进程,这个进程当时在做什么,这时候就需要找到anr文件夹下另外一个文件binderinfo,这里需要找到与我们发起方进程1461通信的是哪个进程

    2_binder等待超时.png

    可以看到是1666号这个进程,再回到trace中看下,这个进程当时在做什么

    3_binder等待超时.png

    可以看到当时对端在做消息的读取,也就是说这里出了问题,很明显这里我们无法修改,我们这个问题在于主线程执行了Binder请求,对端迟迟未返回便很容易出现这个问题,当前做法异步中执行

    案例二:主线程等待锁

    比如下面这个主线程的CallStack例子,可以看到如下信息:

     

    4_主线程等待锁.png

     

    这个案例中gallery的main thread在执行UploaderChimeraService的onDestroy方法时,需要lock 0x23f65d8b,但这个lock有被upload_periodic GCM Task 拿住,这个thread当前是在做连接网络的动作。从这段信息来看,很有可能与测试时手机连接的网络有关,当时连接的事google的网络,由于墙的原因,无法连接gms的相关server有关

    还有一种情况就是死锁,即形成了头尾相连,互相等待的情况,对于这种问题以及上面案例的解决,一般会尝试将锁改为超时锁,比如lock的trylock,超时会自动释放锁,从而避免一直持有锁的情况发生

    案例三:卡在IO上
    这种情况一般是和文件操作相关,判断是否是这种情况,可以看mainlog中搜索关键字"ANR in",看这段信息的最下边,比如下面的信息
    ANRManager: 100% TOTAL: 2% user + 2.1% kernel + 95% iowait + 0.1% softirq
    很明显,IO占比很高,这个时候就需要查看trace日志看当时的callstack,或者在这段ANR点往前看0~4s,看看当时做的什么文件操作,这种场景有遇到过,常见解决方法是对耗时文件操作采取异步操作

    案例四:主线程有耗时的动作
    这种情况是ANR类型问题里遇到最多的,比如网络访问,访问数据库之类的,都很容易造成主线程堵塞,

    这里以访问数据库来说,这类型引起的ANR,一般来讲看当时的CPU使用情况会发现user占比较高,看trace中主线程当时的信息会发现会有一些比如query像ContentProvider这种数据库的动作。这种情况下,还可以去看eventlog或者mainlog,在ANR发生前后打印出来的信息,比如访问数据库这种,在eventlog中搜索"am_anr",然后看前后片段,会发现发生ANR的这个进程有很多数据库相关的信息,说明在发生ANR前后主线程一直在忙于访问数据库,这类型的问题常见于图库,联系人,彩短信应用。

    所以这种问题的解决,一般考虑的是异步解决,异步解决并不是简单的new一个线程,要根据业务场景以及频率来决定,Android常见的异步AsyncTask, IntentService, 线程池(官方四种或自定义), new thread等,一般来说不建议直接new thread

    案例五:binder线程池被占满
    系统对每个process最多分配15个binder线程,这个是谷歌的设计(/frameworks/native/libs/binder/ProcessState.cpp)
    如果另一个process发送太多重复binder请求,那么就会导致接收端binder线程被占满,从而处理不了其它的binder请求
    ,这时候请求端发起的请求就会阻塞等待了(未设置异步请求的前提下),这本身就是系统的一个限制,如果应用未按照系统的要求来实现对应逻辑,那么就会造成问题。
    而系统端是不会(也不建议)通过修改系统行为来兼容应用逻辑,否则更容易造成其它根据系统需求正常编写的应用反而出现不可预料的问题。
    判断Binder是否用完,可以在trace中搜索关键字"binder_f",如果搜索到则表示已经用完,然后就要找log其他地方看是谁一直在消耗binder或者是有死锁发生

    之前有遇到过压力测试手电筒应用,出现BInder线程池被占满情况,解决的思路就是降低极短时间内大量Binder请求的发生,修复的手法是发送BInder请求的函数中做时间差过滤,限定在500ms内最多执行一次

    案例六:JE或者NE导致ANR

    这种场景有遇到过,ANR前出现频繁NE,NE所在的进程与ANR的进程有交互,在解决了NE后,ANR也不复存在,对于这类在ANR前有JE或者NE,一般思路是先解决JE或NE,因为JE/NE发生时会去dump一大堆异常信息,本身也会加重CPU loading,修改完异常后再来看ANR是否还存在,如果还存在,那么就看trace 堆栈,如果不存在,则可以基本判定是JE或NE导致

    案例七:只存在于Monkey测试下
    有些问题是只有在Monkey环境下才能跑出来,平时的user版本用户使用是不会出现的,这种问题的话就没有改动的意义。
    比如下面这个例子:
    ActivityManager: Not finishing activity because controller resumed
    03-18 07:25:50.901 810 870 I am_anr : [0,25443,android.process.media,1086897733,Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)]
    发生这个ANR的原因是Contoller将resume的操作给拦截了, 导致Focus不过去, 从而导致ANR,User版本不会有Contoller, 所以不会出现这个 ANR. 所以这个 ANR 可以忽略.

    展开全文
  • Android ANR简介

    千次阅读 2018-04-04 11:49:32
    1、ANR是什么Application Not Responding即应用无响应。当操作在一段时间内,系统无法处理是,就会发生ANR。弹出对应的无响应的对话框。2、ANR的类型发生ANR的主要是三种类型:A)KeyDispatchTimeout这个Key事件分发...

    1、ANR是什么

    Application Not Responding即应用无响应。

    当操作在一段时间内,系统无法处理是,就会发生ANR。弹出对应的无响应的对话框。

    2、ANR的类型

    发生ANR的主要是三种类型:

    A)KeyDispatchTimeout

    这个Key事件分发超时的时间,Android默认是5秒,主要是定义在ActivityManagerService.java

        // How long we wait until we timeout on key dispatching.
        static final int KEY_DISPATCHING_TIMEOUT = 5*1000;

    B)BroadcastTimeOut

    广播的超时时间,分为FG和BG,分别是10秒和60秒。同样是定义在ActivitManagerService.java

        // How long we allow a receiver to run before giving up on it.
        static final int BROADCAST_FG_TIMEOUT = 10*1000;
        static final int BROADCAST_BG_TIMEOUT = 60*1000;
    

    C)ServiceTimeOut

    Service的超时时间为20秒,定义在ActiveServices.java

        // How long we wait for a service to finish executing.
        static final int SERVICE_TIMEOUT = 20*1000;
    
        // How long we wait for a service to finish executing.
        static final int SERVICE_BACKGROUND_TIMEOUT = SERVICE_TIMEOUT * 10;

    一般发生的ANR,大多都是KeyDispatchTimeout类型。

    3、KeyDispatchTimeout是如何被触发的

       这个部分的code,主要是在InputDispatcher.cpp里面的handleTargetsNotReadyLocked()里面

    int32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
            const EventEntry* entry,
            const sp<InputApplicationHandle>& applicationHandle,
            const sp<InputWindowHandle>& windowHandle,
            nsecs_t* nextWakeupTime, const char* reason) {
        if (applicationHandle == NULL && windowHandle == NULL) {
            if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
                ALOGD("Waiting for system to become ready for input.  Reason: %s", reason);
                mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
                mInputTargetWaitStartTime = currentTime;
                mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
                mInputTargetWaitTimeoutExpired = false;
                mInputTargetWaitApplicationHandle.clear();
            }
        } else {
            if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
                ALOGD("Waiting for application to become ready for input: %s.  Reason: %s",
                        getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
                        reason);
                nsecs_t timeout;
                if (windowHandle != NULL) {
                    timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
                } else if (applicationHandle != NULL) {
                    timeout = applicationHandle->getDispatchingTimeout(
                            DEFAULT_INPUT_DISPATCHING_TIMEOUT);
                } else {
                    timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
                }
    
                mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
                mInputTargetWaitStartTime = currentTime;
                mInputTargetWaitTimeoutTime = currentTime + timeout;
                mInputTargetWaitTimeoutExpired = false;
                mInputTargetWaitApplicationHandle.clear();
    
                if (windowHandle != NULL) {
                    mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
                }
                if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
                    mInputTargetWaitApplicationHandle = applicationHandle;
                }
            }
        }
    
        if (mInputTargetWaitTimeoutExpired) {
            return INPUT_EVENT_INJECTION_TIMED_OUT;
        }
    
        if (currentTime >= mInputTargetWaitTimeoutTime) {
            onANRLocked(currentTime, applicationHandle, windowHandle,
                    entry->eventTime, mInputTargetWaitStartTime, reason);
    
            // Force poll loop to wake up immediately on next iteration once we get the
            // ANR response back from the policy.
            *nextWakeupTime = LONG_LONG_MIN;
            return INPUT_EVENT_INJECTION_PENDING;
        } else {
            // Force poll loop to wake up when timeout is due.
            if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
                *nextWakeupTime = mInputTargetWaitTimeoutTime;
            }
            return INPUT_EVENT_INJECTION_PENDING;
        }
    }

    当applicationHandle == NULL 并且 windowHandle == NULL表示系统未启动完成。把状态设置为INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY

    当系统启动完成后,先获取超时的时间,这个时间就是在AvtivityManagerservice.java中定义的

                if (windowHandle != NULL) {
                    timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
                } else if (applicationHandle != NULL) {
                    timeout = applicationHandle->getDispatchingTimeout(
                            DEFAULT_INPUT_DISPATCHING_TIMEOUT);
                } else {
                    timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT;
                }

    然后把状态设置为INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,并且把超时的时间计算好。

                mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
                mInputTargetWaitStartTime = currentTime;
                mInputTargetWaitTimeoutTime = currentTime + timeout;
                mInputTargetWaitTimeoutExpired = false;
                mInputTargetWaitApplicationHandle.clear();

    在下次事件过来的时候,再次去判断是否超过无响应的限制时间。如果超过就进行无响应的相关操作

        if (currentTime >= mInputTargetWaitTimeoutTime) {//超过无响应的时间限制
            onANRLocked(currentTime, applicationHandle, windowHandle,
                    entry->eventTime, mInputTargetWaitStartTime, reason);
    
            // Force poll loop to wake up immediately on next iteration once we get the
            // ANR response back from the policy.
            *nextWakeupTime = LONG_LONG_MIN;
            return INPUT_EVENT_INJECTION_PENDING;
        } 

    4、当ANR发生了,ActivityManagerservice做了什么

    主要是ActivityManagerservice.java的appNotResponding()

        final void appNotResponding(ProcessRecord app, ActivityRecord activity,
                ActivityRecord parent, boolean aboveSystem, final String annotation) {
    
    		ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
            SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
            
            if (mController != null) { // mController是IActivityController接口的实例,是为Monkey测试程序预留的,默认为null
                try {
                    // 0 == continue, -1 = kill process immediately
                    int res = mController.appEarlyNotResponding(app.processName, app.pid, annotation);
                    if (res < 0 && app.pid != MY_PID) {
                        app.kill("anr", true);
                    }
                } catch (RemoteException e) {
                    mController = null;
                    Watchdog.getInstance().setActivityController(null);
                }
            }
    
            long anrTime = SystemClock.uptimeMillis();
            if (MONITOR_CPU_USAGE) {
               // 更新CPU状态信息
                updateCpuStatsNow();
            }
    
            synchronized (this) {
                //系统关机、进程已经处于anr状态、crash状态,这些情况下忽略
                // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
                if (mShuttingDown) {
                    Slog.i(TAG, "During shutdown skipping ANR: " + app + " " + annotation);
                    return;
                } else if (app.notResponding) {
                    Slog.i(TAG, "Skipping duplicate ANR: " + app + " " + annotation);
                    return;
                } else if (app.crashing) {
                    Slog.i(TAG, "Crashing app skipping ANR: " + app + " " + annotation);
                    return;
                }
    
    	    //为了防止多次对相同app的anr执行重复代码,在此处标注记录
                // In case we come through here for the same app before completing
                // this one, mark as anring now so we will bail out.
                app.notResponding = true;
    
                // Log the ANR to the event log. 输出ANR信息到event log
                EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
                        app.processName, app.info.flags, annotation);
    
                 // 添加当前app到firstpids列表中
                // Dump thread traces as quickly as we can, starting with "interesting" processes.
                firstPids.add(app.pid);
    
    	    // 添加当前app的parentPid到firstpids列表中
                int parentPid = app.pid;
                if (parent != null && parent.app != null && parent.app.pid > 0) parentPid = parent.app.pid;
                if (parentPid != app.pid) firstPids.add(parentPid);
    
                // 添加system_server到firstpids列表中
                if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);
    
    			//根据是否常驻内存分别添加到firstPids和lastPids
                for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
                    ProcessRecord r = mLruProcesses.get(i);
                    if (r != null && r.thread != null) {
                        int pid = r.pid;
                        if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
                            if (r.persistent) {
                                firstPids.add(pid);
                            } else {
                                lastPids.put(pid, Boolean.TRUE);
                            }
                        }
                    }
                }
            }
    
    	/*
    	将ANR信息存在info变量中,后续打印到LOGCAT,这部分的信息会以ActivityManager为Tag打印出来
    	包含了ANR的进程,出现原因以及当时的CPU状态,这些对分析ANR是非常重要的信息
    	*/
            // Log the ANR to the main log.
            StringBuilder info = new StringBuilder();
            info.setLength(0);
            info.append("ANR in ").append(app.processName);
            if (activity != null && activity.shortComponentName != null) {
                info.append(" (").append(activity.shortComponentName).append(")");
            }
            info.append("\n");
            info.append("PID: ").append(app.pid).append("\n");
            if (annotation != null) {
                info.append("Reason: ").append(annotation).append("\n");
            }
            if (parent != null && parent != activity) {
                info.append("Parent: ").append(parent.shortComponentName).append("\n");
            }
    
            final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
    
    		// 将ANR信息输出到traces文件
            File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
                    NATIVE_STACKS_OF_INTEREST);
    
            String cpuInfo = null;
            if (MONITOR_CPU_USAGE) {
    		    //再次获取CPU的信息
                updateCpuStatsNow();
                synchronized (mProcessCpuTracker) {
                    cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);
                }
                info.append(processCpuTracker.printCurrentLoad());
                info.append(cpuInfo);
            }
    
            info.append(processCpuTracker.printCurrentState(anrTime));
    
    	//  输出到main log
            Slog.e(TAG, info.toString());
            if (tracesFile == null) {
                // There is no trace file, so dump (only) the alleged culprit's threads to the log
                Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
            }
    
    	// 将ANR信息导入到DropBox目录下,也就是说除了traces文件还会有一个dropbox文件用于记录ANR
            addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
                    cpuInfo, tracesFile, null);
    
            if (mController != null) {
                try {
                    // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
                    int res = mController.appNotResponding(app.processName, app.pid, info.toString());
                    if (res != 0) {
                        if (res < 0 && app.pid != MY_PID) {
                            app.kill("anr", true);
                        } else {
                            synchronized (this) {
                                mServices.scheduleServiceTimeoutLocked(app);
                            }
                        }
                        return;
                    }
                } catch (RemoteException e) {
                    mController = null;
                    Watchdog.getInstance().setActivityController(null);
                }
            }
    
            // Unless configured otherwise, swallow ANRs in background processes & kill the process.
            boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                    Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
    
            synchronized (this) {
                 //主动通知battery state service,发生了ANR
                mBatteryStatsService.noteProcessAnr(app.processName, app.uid);
    
                if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {
                    app.kill("bg anr", true);
                    return;
                }
    
                // Set the app's notResponding state, and look up the errorReportReceiver
                makeAppNotRespondingLocked(app,
                        activity != null ? activity.shortComponentName : null,
                        annotation != null ? "ANR " + annotation : "ANR",
                        info.toString());
    
    			//弹出无响应的对话框
                // Bring up the infamous App Not Responding dialog
                Message msg = Message.obtain();
                HashMap<String, Object> map = new HashMap<String, Object>();
                msg.what = SHOW_NOT_RESPONDING_MSG;
                msg.obj = map;
                msg.arg1 = aboveSystem ? 1 : 0;
                map.put("app", app);
                if (activity != null) {
                    map.put("activity", activity);
                }
    
                mHandler.sendMessage(msg);
            }
        }

       主要是dump相关的信息到traces文件里面File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST);

    输出main log信息  Slog.e(TAG, info.toString());

    发生ANR的信息导入到dropbox目录下  addErrorToDropBox("anr", app, app.processName, activity, parent, annotation, cpuInfo, tracesFile, null);

    最后根据条件,来判断是否要弹出无响应的对话框。

    4、如何根据log来分析ANR

    4.1 一般要先分析Main log

      a)    先在Main log里面搜索关键字 “ANR”,确定是否真的有发生ANR。

      b) 查看在ANR之前,系统是否发生了JE(Java Exception)或者NE(Native Exception),有时候一些ANR是由JE或者NE引起的。

      c)  在发生ANR的地方,查看对应的log信息。

            例如:

    05-01 23:03:24.603 E/ActivityManagerService( 1573): ANR in com.tpv.xmic.contentbrowser.ebony2k15 (com.tpv.xmic.contentbrowser.ebony2k15/com.tpv.xmic.mediacenter.player.videoplayer.VideoPlayerActivity)
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573): PID: 3109
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573): Reason: Input dispatching timed out (Waiting to send key event because the focused window has not finished processing all of the input events that were previously delivered to it.  Outbound queue length: 0.  Wait queue length: 1.)
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573): Load: 6.44 / 5.38 / 5.07
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573): CPU usage from 0ms to 8532ms later:
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   52% 1165/logd: 50% user + 2.4% kernel / faults: 2 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   35% 1573/system_server: 13% user + 21% kernel / faults: 9349 minor 58 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   13% 1193/tvos: 8.5% user + 4.5% kernel / faults: 1 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   11% 1176/mediaserver: 5.9% user + 5.2% kernel / faults: 317 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   8.6% 3137/com.tpv.xmic.contentbrowser.ebony2k15:MediaScanService: 4.9% user + 3.7% kernel / faults: 2340 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   4.2% 3109/com.tpv.xmic.contentbrowser.ebony2k15: 2.9% user + 1.2% kernel / faults: 3049 minor 72 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   6.4% 1170/surfaceflinger: 4.2% user + 2.2% kernel / faults: 129 minor 1 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   6.4% 17981/ntfs-3g: 2.6% user + 3.7% kernel / faults: 157 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   5.9% 2624/com.mstar.android.providers.tv: 3.6% user + 2.3% kernel / faults: 3514 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   5.8% 1783/com.android.systemui: 2.6% user + 3.1% kernel / faults: 3578 minor 4 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   3.1% 1806/com.mstar.tv.service: 1.6% user + 1.4% kernel / faults: 3161 minor 2 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 1174/debuggerd64: 0% user + 0% kernel / faults: 5068 minor 11 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2458/com.tpv.contextualSetting: 0% user + 0% kernel / faults: 3146 minor 1 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.2% 2386/com.ktcp.autoupgrade: 0.1% user + 0% kernel / faults: 2423 minor 1 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   1.8% 2302/org.droidtv.dlna: 0.9% user + 0.9% kernel / faults: 2193 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2440/com.tpv.functionadjust: 0% user + 0% kernel / faults: 1841 minor 1 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2147/com.tpv.bluetooth: 0% user + 0% kernel / faults: 1854 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2168/com.tpv.setting: 0% user + 0% kernel / faults: 2254 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2366/com.xmic.screenmirror: 0% user + 0% kernel / faults: 2468 minor 9 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2422/com.tpv.xmic.smartrc.ots2k15: 0% user + 0% kernel / faults: 1835 minor 4 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2199/com.tpv.xmic.smartrc.ebony2k14: 0% user + 0% kernel / faults: 2221 minor 23 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2323/com.tpv.xmic.ap: 0% user + 0% kernel / faults: 2297 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   1% 2404/com.tpv.xmic.recordersreminders.ebony2k15: 0.4% user + 0.6% kernel / faults: 2172 minor 13 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   2.4% 3400/mstar.tvsetting.factory.ui: 1.4% user + 1% kernel / faults: 1699 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2251/com.tpv.xmic.dbcservice: 0% user + 0% kernel / faults: 1873 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2348/com.redbend.client: 0% user + 0% kernel / faults: 2026 minor 7 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2276/com.mstar.android.pppoe: 0% user + 0% kernel / faults: 2276 minor 3 major
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 1710/android.process.media: 0% user + 0% kernel / faults: 1957 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2067/com.xmic.voice: 0% user + 0% kernel / faults: 1903 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2108/com.tpv.ebony2K15_AppSource: 0% user + 0% kernel / faults: 1914 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   1.4% 17957/usb-storage: 0% user + 1.4% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   1.2% 682/mmcqd/0: 0% user + 1.2% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2221/com.tpv.xmic.dlna.dmr: 0% user + 0% kernel / faults: 2032 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.5% 3361/logcat: 0.1% user + 0.4% kernel / faults: 2 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.4% 16087/kworker/0:0: 0% user + 0.4% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.3% 1181/livecap: 0.2% user + 0.1% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 3/ksoftirqd/0: 0% user + 0.1% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 12/ksoftirqd/1: 0% user + 0.1% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 319/ion_system_heap: 0% user + 0.1% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.2% 1142/jbd2/mmcblk0p14: 0% user + 0.2% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.2% 1190/adbd: 0% user + 0.2% kernel / faults: 102 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 8/rcu_preempt: 0% user + 0% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 1180/virtualkeypad: 0% user + 0% kernel / faults: 1 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 1953/com.android.inputmethod.pinyin: 0% user + 0% kernel / faults: 3 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 2773/mstar.tvsetting.factory.ui:remote: 0% user + 0% kernel / faults: 1 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 3286/RTW_CMD_THREAD: 0% user + 0% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 3309/com.tpv.ebony2k15.joystick: 0% user + 0% kernel / faults: 5 minor
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0.1% 16074/kworker/2:1: 0% user + 0.1% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 17662/kworker/1:0: 0% user + 0% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   0% 17796/kworker/1:1: 0% user + 0% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573):  +0% 18070/kworker/3:0: 0% user + 0% kernel
    
    05-01 23:03:24.603 E/ActivityManagerService( 1573): 73% TOTAL: 35% user + 25% kernel + 12% iowait + 0%
    

     如上的log信息,解读如下:

    发生ANR的时间为 05-01 23:03:24.603

    对应的进程为 com.tpv.xmic.contentbrowser.ebony2k15

    ANR的进程号为PID: 3109

    ANR的原因为  Input dispatching timed out

    发生ANR后的CPU信息:

    05-01 23:03:24.603 E/ActivityManagerService( 1573): CPU usage from 0ms to 8532ms later:
    05-01 23:03:24.603 E/ActivityManagerService( 1573):   52% 1165/logd: 50% user + 2.4% kernel / faults: 2 minor
    ...
    05-01 23:03:24.603 E/ActivityManagerService( 1573): 73% TOTAL: 35% user + 25% kernel + 12% iowait + 0%

    根据现有的log信息还是无法确定ANR的根源。需要进一步的去分析对应的traces文件。

    main log里面的ANR输出格式大致如下

    ActivityManager: ANR in [Process Name]([short component name]) 
    ActivityManager: PID: [Process Pid] 
    ActivityManager: Reason: [Annotation]  
    ActivityManager: Parent: [short component name of parent] 
    ActivityManager: Load: [Load1] / [Load5] / [Load15]  
    ActivityManager: CPU usage from [上次采样与现在的时间差] ms to [当前采样与现在的时间差] ms  ago/later:  
    ActivityManager: [总的CPU时间占用率]% [PID]/[Process Name]: [用户CPU时间占用率]% user + [系统 CPU时间占用率]% kernel + [IO等待CPU时间占用率]% iowait + [硬中断CPU时间占用率]% irq + [软中断CPU时间占用率]% softirq / faults: [次要页错误/主要页错误] minor/major  
    ActivityManager: .....  
    ActivityManager: [CPU时间占用率合计统计]
    

    有时候main log里面的cpu相关信息就可以大致确定ANR的原因,例如JE、 NE、  CPU  100% 等等


    4.2 Traces文件的分析

    一个Traces文件,不同的系统有差异,格式大致如下:

    ----- pid 3109 at 2015-05-01 23:03:16 -----
    Cmd line: com.tpv.xmic.contentbrowser.ebony2k15
    ABI: arm
    Build type: optimized
    Loaded classes: 4083 allocated classes
    Intern table: 5645 strong; 1324 weak
    JNI: CheckJNI is on; globals=330 (plus 1 weak)
    
    Heap: 17% free, 29MB/35MB; 221169 objects
    Dumping cumulative Gc timings
    Start Dumping histograms for 47 iterations for concurrent mark sweep
    ...
    Total time spent in GC: 4.653s
    Mean GC size throughput: 15MB/s
    Mean GC object throughput: 264330 objects/s
    Total number of allocations 1451323
    Total bytes allocated 103MB
    Free memory 6MB
    Free memory until GC 6MB
    Free memory until OOME 226MB
    Total memory 35MB
    Max memory 256MB
    Total mutator paused time: 380.545ms
    Total time waiting for GC to complete: 247.672us
    
    DALVIK THREADS (30):
    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 obj=0x74a26ff8 self=0xf5007800
      | sysTid=3109 nice=0 cgrp=apps sched=0/0 handle=0xf7701ec8
      | state=S schedstat=( 0 0 0 ) utm=4101 stm=537 core=0 HZ=100
      | stack=0xff6fa000-0xff6fc000 stackSize=8MB
      | held mutexes=
      kernel: __switch_to+0x74/0x8c
      kernel: binder_thread_read+0x8a8/0x1004
      kernel: binder_ioctl+0x6b0/0x97c
      kernel: compat_sys_ioctl+0xb0/0x15c8
      kernel: el0_svc_naked+0x34/0x38
      native: #00 pc 00039ae8  /system/lib/libc.so (__ioctl+8)
      native: #01 pc 00051b9d  /system/lib/libc.so (ioctl+14)
      native: #02 pc 0001f3e7  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+190)
      native: #03 pc 0001fa5b  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+42)
      native: #04 pc 0001fc1d  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+124)
      native: #05 pc 0001ad47  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+30)
      native: #06 pc 000629ff  /system/lib/libmedia.so (???)
      native: #07 pc 0005f757  /system/lib/libmedia.so (android::MediaPlayer::disconnect()+46)
      native: #08 pc 0001ef5d  /system/lib/libmedia_jni.so (???)
      native: #09 pc 000058d3  /data/dalvik-cache/arm/system@framework@boot.oat (Java_android_media_MediaPlayer__1release__+82)
      at android.media.MediaPlayer._release(Native method)
      at android.media.MediaPlayer.release(MediaPlayer.java:1472)
      ...
      at android.view.KeyEvent.dispatch(KeyEvent.java:2617)
      at android.app.Activity.dispatchKeyEvent(Activity.java:2720)
      at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2737)
      at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4098)
      at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4060)
      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3629)
      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3682)
      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3648)
      at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3758)
      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3656)
      at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3815)
      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3629)
      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3682)
      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3648)
      at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3656)
      at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3629)
      at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3682)
      at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3648)
      at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3791)
      at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3952)
      at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2208)
      at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1849)
      at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1840)
      at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:2185)
      at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
      at android.os.MessageQueue.nativePollOnce(Native method)
      at android.os.MessageQueue.next(MessageQueue.java:143)
      at android.os.Looper.loop(Looper.java:122)
      at android.app.ActivityThread.main(ActivityThread.java:5409)
      at java.lang.reflect.Method.invoke!(Native method)
      at java.lang.reflect.Method.invoke(Method.java:372)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:902)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:697)

    a)Traces文件里面的相关信息要和main log对应上,才能确保是同一个问题

    ----- pid 3109 at 2015-05-01 23:03:16 -----
    Cmd line: com.tpv.xmic.contentbrowser.ebony2k15

    这里的pid为3109 ,时间为2015-05-01 23:03:16,进程名为com.tpv.xmic.contentbrowser.ebony2k15。

    和mainlog是 一 一对应的,说明是发生ANR对应的traces文件。

    b)这个问题的trace文件里面描述的清楚,主要发生ANR的原因在于内存过低,不停的GC

    Free memory 6MB

    c)当然trace里面的相关信息,也有必要做一下解读。

    DALVIK THREADS (30):
    "main" prio=5 tid=1 Native
      | group="main" sCount=1 dsCount=0 obj=0x74a26ff8 self=0xf5007800
      | sysTid=3109 nice=0 cgrp=apps sched=0/0 handle=0xf7701ec8
      | state=S schedstat=( 0 0 0 ) utm=4101 stm=537 core=0 HZ=100
      | stack=0xff6fa000-0xff6fc000 stackSize=8MB
      | held mutexes=

    第1行:

    DALVIK THREADS这个是固定的格式,指明下面都是当前运行的dalvik threads

    第2行:

    main为当前线程的名字,(有的线程后面会有daemon,表示为守护进程)

    prio表示为优先级,默认值为5

    tid表示为thread id,tid为1表示为正在运行的thread

    Native表示为线程的状态。线程的状态都是定义在Thread.cpp里面的。具体如下表


    第3行:

    线程组的名字:group =“main”

    sCount =1,(suspend cound)表示线程被挂起的次数为1次

    dsCount =0,(debug suspend count)表示线程被调试挂起的次数为0

    obj=0x74a26ff8,这个是线程的java对象的地址

    self=0xf5007800,这个是线程本身的地址

    第4行:

    sysTid=3109,线程在linux系统下得本地线程id (sysTid和PID相同)

    nice=0, 这个是线程的调度优先级

    cgrp=apps ,这个是线程调度所属的组。

    sched=0/0,线程调度的策略

    handle= 0xf7701ec8,处理函数地址。

    第5行:

    state=S, 是调度状态

    schedstat=( 0  0 0 ),这个是从 /proc/[pid]/task/[tid]/schedstat读出,三个值分别表示线程在cpu上执行的时间、线程的等待时间和线程执行的时间片长度。有的android内核版本不支持这项信息,得到的三个值都是0

    utm=4101,线程用户态下使用的时间值(单位是jiffies)。

    stm=573,内核态下得调度时间值(单位是jiffies)。

    core=0,最后运行该线程的cup序号,即序号为0的CPU运行该线程。

    第6行:

    stack=0xff6fa000-0xff6fc000,表示线程栈地址范围

    stackSize=8MB,表示线程栈的大小为8M。通过(0xff6fc000-0xff6fa000 = 0x2000=8M)计算得到

    d)接下来就是函数的调用堆栈了。

    这个部分,有时候进一步分析ANR的具体原因的时候,需要进一步去看对应的 source code。通过调用堆栈可以快递定位到对应的文件和函数。

     kernel: __switch_to+0x74/0x8c
      kernel: binder_thread_read+0x8a8/0x1004
      kernel: binder_ioctl+0x6b0/0x97c
      kernel: compat_sys_ioctl+0xb0/0x15c8
      kernel: el0_svc_naked+0x34/0x38
      native: #00 pc 00039ae8  /system/lib/libc.so (__ioctl+8)
      native: #01 pc 00051b9d  /system/lib/libc.so (ioctl+14)
      native: #02 pc 0001f3e7  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+190)
      native: #03 pc 0001fa5b  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+42)
      native: #04 pc 0001fc1d  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+124)
      native: #05 pc 0001ad47  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+30)
      native: #06 pc 000629ff  /system/lib/libmedia.so (???)
      native: #07 pc 0005f757  /system/lib/libmedia.so (android::MediaPlayer::disconnect()+46)
      native: #08 pc 0001ef5d  /system/lib/libmedia_jni.so (???)
      native: #09 pc 000058d3  /data/dalvik-cache/arm/system@framework@boot.oat (Java_android_media_MediaPlayer__1release__+82)
      at android.media.MediaPlayer._release(Native method)
      at android.media.MediaPlayer.release(MediaPlayer.java:1472)
      ...
      at android.view.KeyEvent.dispatch(KeyEvent.java:2617)
      at android.app.Activity.dispatchKeyEvent(Activity.java:2720)

    例如:

    at android.media.MediaPlayer.release(MediaPlayer.java:1472)

    表示对应的包名为android.media.MediaPlayer的release()函数。

    文件名为MediaPlayer.java的第1472行。


    一般来说Trace文件顶部的线程是ANR的元凶。这里只是举一个例子。

    当然,发生ANR的原因各不同,需要根据具体的问题做具体的分析。


    5、如何避免AR呢

    与其事后来解决ANR的问题,不如在开发的过程中多注意,避免发生ANR。

    总结一些需要注意的实现如下:

    a)UI主线程尽量只做跟UI相关的工作.

    b) 耗时的操作,如I/O,网络连接,把它放入单独的线程处理

    c) 尽量用Handler来处理UI线程和非UI线程之间的交互


    展开全文
  • ANR 详解

    2017-11-20 13:01:44
    ANR 定义 ANR 也就是 "应用无响应" ,当操作在一段时间内使得系统无法处理时,系统层面会弹出应用程序无响应对话框。(一个流畅的合理的应用程序中不能出现该对话框,所以响应性能的设计很重要,这样系统不会显示...
  • 压测中Android 系统稳定性 - ANR

    千次阅读 2019-03-23 11:03:25
    ANR简介(什么是ANR、为什么会有ANRANR的异常长什么样) 如何分析ANR(引起ANR的原因分类、分析ANR的利器) 实例讲解 避免ANR的最佳实践(从错误中吸取教训) 1.1 ANR简介 ANR,是...
  • 什么是ANR? 如何避免它?

    千次阅读 2017-03-16 20:12:49
    什么是ANR? 用户行为 Android不同组件ANR的超时时间不同 解决方案 一、什么是ANRANR,全称为Application Not Responding。在Android 中,如果你的应用程序有一段时间没有响应,系统会向用户显示一个对话框,这...
  • Android ANR 详解

    万次阅读 2017-05-02 08:00:55
    ANR简介 ANR,是“Application Not Responding”的缩写,即“应用程序无响应”。在Android中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会监测应用程序的响应时间,如果应用程序主线程...
  • ANR

    千次阅读 2018-10-14 20:53:41
    当Android应用程序的UI线程被阻止太长时,会触发“应用程序无响应”(ANR)错误。如果应用程序位于前台,系统会向用户显示一个对话框,如图1所示.ANR对话框使用户有机会强制退出应用程序。 图1.向用户显示的ANR...
  • ANR 原理与实战技巧

    千次阅读 2017-09-02 12:01:33
    首先,每天看到不断有新人关注着这个公众号,心情很是愉悦。一种认可,一种信任,也是我前进的动力。感谢大家的支持与鼓励。  如果你喜欢这篇文章,或者喜欢这个图片,或者有所感悟,或者仅仅因为喜欢代码GG,分享...
  • 用C++实现“按任意键继续

    万次阅读 2015-10-28 21:46:39
    很久没有写过C++程序了,对Visual Studio有些不习惯。尤其对它编译后直接退出感到无语到愤怒。。。 于是就谷歌度娘都访问了一下,发现有几下方法: 1.直接调用系统函数 system("pause");...
  • 按任意键继续/退出

    千次阅读 2014-06-26 18:14:00
    #按任意键继续: Write-Host "请按任意键继续..."$null = [System.Console]::ReadKey()     #任意键退出: Write-Host "请按任意键继续..."$null = [System.Console]::ReadKey()...
  • 在C语言中如何实现按任意键继续

    千次阅读 2019-02-14 20:48:57
    1、直接调用系统函数 system(“pause”): system()会调用fork()产生子进程, 由子进程来调用/bin/sh-c string 来执行参数string 字符串所代表的命令, 此...此函数是一个不回显函数,当用户下某个字符时,函数自...
  • Python下实现按任意键继续

    万次阅读 2018-11-12 11:25:22
    问题:如何在python中实现按任意键退出? 分析:要实现此功能,思路是让程序处于暂停状态,等待并捕捉用户的一个键盘输入,然后继续执行。 方案:我们可以利用python的内建库来实现,下面分别就Windows和linux给出...
  • 只需要在return 0;前面加上system(“pause>nul”);即可
  • Python 按任意键继续...(Windows)

    千次阅读 2017-11-26 21:30:00
    1、回车键退出。 1 2 ...raw_input(unicode('回车键退出...','utf-8').encode('gbk')) ...2、按任意键继续。 1 2 importos os.system('pause') *** 本文转自walker snapsho...
  • [C++] 用C++实现“按任意键继续

    千次阅读 2013-03-10 13:09:38
    很久没有写过C++程序了,对Visual Studio有些不习惯。尤其对它编译后直接退出感到无语到愤怒。。。  http://blog.sina.com.cn/blogagn 于是就谷歌访问了一下,发现有几下方法: ...int main
  • linux下C语言实现按任意键继续~~

    千次阅读 2011-08-18 09:46:46
    #include #include #include #include static struct termios stored_settings; void set_keypress (void) {  struct termios new_setti
  • C++ 实现按任意键继续~~~

    万次阅读 2010-09-20 21:10:00
    C++ 实现按任意键继续~~~
  • 这个找了很久,因为安装tomcat服务,会出现请按任意键继续,但后面我还有指令的,不想让用户再点击键盘,自动执行最好,所以只需要在脚本文件的最上面添加如下,就可以自动执行,不会弹出文字了: @echo offnul
  • 资料来源: 转博客 http://blog.csdn.net/chy19890820/article/details/8773431 http://blog.csdn.net/xingjiarong/article/details/50590685 ... 还有 I love matlab 
  • golang 按任意键继续

    千次阅读 2016-06-22 20:56:10
    golang 按任意键继续...
  • 在微软的官方网站,vs2013和vs2010的改动就是没有像之前的vs05 08将空工程默认为console的,所以才不会显示按任意键退出, 一闪而过。通过手动将这个设置了,就会使得控制台像原来的一样显示按任意键退出。...
  • 在return语句前加上 system("pause");
  • BASH中用 read 实现“按任意键继续

    千次阅读 2013-08-14 20:01:30
    BASH中用 read 实现“按任意键继续” read -s -n1 -p "按任意键继续 ... " Debug Android native code http://blog.csdn.net/johnnylq/article/details/6401878
  • #include stdio.h> #include stdlib.h> #include termios.h> #include unistd.h> int getch(); void press_key(); int main() {  printf("Hel
  • 常见的3种能让程序在运行时调试时暂停,按任意键继续的方法: 1,getch(); 所在头文件:conio.h (conio是Console Input/Output(控制台输入输出)的简写,不是C标准库中的头文件,其中定义了通过控制台进行...
  • 在VS2010里的控制台应用程序在运行时,结果画面一闪而过,不管是用F5 还是用Ctrl + F5都是一样,导致无法看到结果。   网上有不少的办法,说是都是在程序最后加一个要程序暂停的语句( system("pause");...
  • 方法一在main函数的return语句前加一句 system("pause");使用该函数时,需要加载头文件#include &lt;stdlib.h&gt;方法二通过更改以下设置:项目-&gt;属性-&...控制台 增加“/SUBSYSTEM:...
  • C/C++实现任意键继续功能

    千次阅读 2018-06-25 02:17:34
    当我们在使用系统命令:stop时会在终端下弹出:任意键继续的代码!这里只需要C/C++自带的函数即可:kbhit函数原型:int kbhit(void);返回值:如果有按键下返回非0否则返回0函数介绍:此函数是C/C++里的一个...

空空如也

1 2 3 4 5 ... 20
收藏数 172,590
精华内容 69,036
关键字:

anr