ANR 问题分析

本文记录了一次Android应用出现ANR(应用程序无响应)的问题分析过程。通过trace文件,发现主线程因Binder调用阻塞,子线程中有多个数据库查询任务导致Binder线程池满,从而引发ANR。分析指出数据库查询延迟可能是问题关键,后续将深入调查数据库性能。
摘要由CSDN通过智能技术生成

工作中遇到一个ANR问题,记录下自己的想法,随笔而已~ 

ANR 原因是key没有响应,应该是主线程卡住了,key没有被送上来。

07-28 11:51:58.362  3531  3648 I InputDispatcher: Application is not responding: AppWindowToken{5eb8975 token=Token{52048ac ActivityRecord{136365f u0  Skip=false org.droidtv.xxx/.MainActivity t25}}} - Window{8ea8879 u0 org.droidtv.xxx/org.droidtv.xxx.MainActivity}.  It has been 5003.5ms since event, 5001.3ms since wait started.  Reason: 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.

附上同事说的key事件传递流程:

key->decorview->activity->phonewindow->ui->input系统

那么主线程为什么卡住了?从log完全看不出来哪里卡住了,主线程接收的每个key都及时处理了也没有做任何耗时操作。

那就看下trace文件吧。。

"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x71b631f0 self=0xe925ce00
  | sysTid=5426 nice=-10 cgrp=default sched=0/0 handle=0xe97f5dc0
  | state=S schedstat=( 11840933002 3428817922 40300 ) utm=1029 stm=154 core=1 HZ=100
  | stack=0xff57d000-0xff57f000 stackSize=8192KB
  | held mutexes=
  kernel: (couldn't read /proc/self/task/5426/stack)
  native: #00 pc 000962b0  /apex/com.android.runtime/lib/bionic/libc.so (__ioctl+8)
  native: #01 pc 00064c7d  /apex/com.android.runtime/lib/bionic/libc.so (ioctl+28)
  native: #02 pc 0003aa81  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+208)
  native: #03 pc 0003b56f  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+26)
  native: #04 pc 0003b381  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+112)
  native: #05 pc 00033ed1  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
  native: #06 pc 000db8a3  /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+82)
  at android.os.BinderProxy.transactNative(Native method)
  at android.os.BinderProxy.transact(BinderProxy.java:510)
  at android.database.BulkCursorProxy.close(BulkCursorNative.java:216)
  at android.database.BulkCursorToCursorAdaptor.close(BulkCursorToCursorAdaptor.java:121)
  at android.database.CursorWrapper.close(CursorWrapper.java:54)
  at android.content.ContentResolver$CursorWrapperInner.close(ContentResolver.java:3336)
  at android.content.CursorLoader.onCanceled(CursorLoader.java:180)
  at android.content.CursorLoader.onCanceled(CursorLoader.java:46)
  at android.content.AsyncTaskLoader.dispatchOnCancelled(AsyncTaskLoader.java:249)
  at android.content.AsyncTaskLoader$LoadTask.onCancelled(AsyncTaskLoader.java:108)
  at android.os.AsyncTask.finish(AsyncTask.java:753)
  at android.os.AsyncTask.access$900(AsyncTask.java:192)
  at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:772)
  at android.os.Handler.dispatchMessage(Handler.java:107)
  at android.os.Looper.loop(Looper.java:214)
  at android.app.ActivityThread.main(ActivityThread.java:7356)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

ANR 期间没有多少log打印,所以trace文件记录应该就是案发现场。从上面的调用栈可以看出,ANR 是发生在LoaderManager的方法中(通过查看源码应该是 restartLoader )。这部分代码为什么突然就出现问题了??系统当时在干嘛??

带着这个疑问查了挺多资料,发现如下两行log可以看出是binder call 阻塞了,在等待对端的回应。这部分是在主线程完成的,所以导致了ANR 的发生。

  native: #03 pc 0003b56f  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+26)
  at android.os.BinderProxy.transactNative(Native method)
 

继续看trace文件, 发现子线程中有十几个任务在做查询,binder call 也都阻塞了。所以应该是binder 线程池被占满了,导致主线程卡住了。

  "AsyncTask #9" prio=5 tid=27 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x136835d0 self=0xd3eee000
  | sysTid=9025 nice=10 cgrp=default sched=0/0 handle=0xbb806230
  | state=S schedstat=( 24568742 45875255 164 ) utm=1 stm=0 core=1 HZ=100
  | stack=0xbb703000-0xbb705000 stackSize=1040KB
  | held mutexes=
  kernel: (couldn't read /proc/self/task/9025/stack)
  native: #00 pc 000962b0  /apex/com.android.runtime/lib/bionic/libc.so (__ioctl+8)
  native: #01 pc 00064c7d  /apex/com.android.runtime/lib/bionic/libc.so (ioctl+28)
  native: #02 pc 0003aa81  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+208)
  native: #03 pc 0003b56f  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+26)
  native: #04 pc 0003b381  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+112)
  native: #05 pc 00033ed1  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
  native: #06 pc 000db8a3  /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+82)
  at android.os.BinderProxy.transactNative(Native method)
  at android.os.BinderProxy.transact(BinderProxy.java:510)
  at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
  at android.content.ContentResolver.query(ContentResolver.java:944)
  at android.content.ContentResolver.query(ContentResolver.java:880)
  at android.content.CursorLoader.loadInBackground(CursorLoader.java:71)
  at android.content.CursorLoader.loadInBackground(CursorLoader.java:46)
  at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:321)
  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:74)
  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:62)
  at android.os.AsyncTask$3.call(AsyncTask.java:378)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:919)
  
  "AsyncTask #23" prio=5 tid=46 Native
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x134d5708 self=0xb9ca7a00
  | sysTid=9108 nice=10 cgrp=default sched=0/0 handle=0xb7b67230
  | state=S schedstat=( 745167 32750 4 ) utm=0 stm=0 core=3 HZ=100
  | stack=0xb7a64000-0xb7a66000 stackSize=1040KB
  | held mutexes=
  kernel: (couldn't read /proc/self/task/9108/stack)
  native: #00 pc 000962b0  /apex/com.android.runtime/lib/bionic/libc.so (__ioctl+8)
  native: #01 pc 00064c7d  /apex/com.android.runtime/lib/bionic/libc.so (ioctl+28)
  native: #02 pc 0003aa81  /system/lib/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+208)
  native: #03 pc 0003b56f  /system/lib/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+26)
  native: #04 pc 0003b381  /system/lib/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+112)
  native: #05 pc 00033ed1  /system/lib/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+36)
  native: #06 pc 000db8a3  /system/lib/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+82)
  at android.os.BinderProxy.transactNative(Native method)
  at android.os.BinderProxy.transact(BinderProxy.java:510)
  at android.content.ContentProviderProxy.query(ContentProviderNative.java:421)
  at android.content.ContentResolver.query(ContentResolver.java:944)
  at android.content.ContentResolver.query(ContentResolver.java:880)
  at android.content.CursorLoader.loadInBackground(CursorLoader.java:71)
  at android.content.CursorLoader.loadInBackground(CursorLoader.java:46)
  at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:321)
  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:74)
  at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:62)
  at android.os.AsyncTask$3.call(AsyncTask.java:378)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
  at java.lang.Thread.run(Thread.java:919)

再回到 log 去看,发现APP接收到按键后就会去做一次数据库查询,这部分逻辑没有问题。但是数据库查询结果一直没有返回。结合trace可以看出,子线程查询时 binder 一直在等待对端数据库返回结果,结果没有返回就会导致阻塞。

下一步就得看下数据库啦~

不足多多,欢迎指教~

参考:

https://www.jianshu.com/p/18f16aba79dd

https://blog.csdn.net/u014630142/article/details/110049575


  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值