Binder开辟线程数过多导致主线程ANR异常


一、Binder线程数目

一起了解 binder 线程池的前生今世。

在android系统中,通过binder进行IPC时,服务端总是会起一些Binder线程来响应客户端的请求。这里面就涉及到通过BInder线程池 开辟binder线程。

那这些Binder线程又是如何创建,如何管理的呢?

在APP进程创建或者AIDL服务进程在创建的时候,AMS就会通知Zygote进程fork一个APP进程,在Zygote进程中初始化该APP进程的时候,会调用到Native层的app_main.cpp中的onZygoteInit()。

在frameworks/base/cmds/app_process/app_main.cpp中

  virtual void onZygoteInit()
  {
      sp<ProcessState> proc = ProcessState::self();
      ALOGV("App process: starting thread pool.\n");
      proc->startThreadPool(); //开启了线程池
  }

对于Binder线程池的个数,在为当前进程创建ProcessState的时候,通过mMaxThread传入了Binder驱动可创建的最大Binder线程数,默认为15个。

在这里插入图片描述
这个变量在最前面已经定义死了。

native/libs/binder/ProcessState.cpp

#define DEFAULT_MAX_BINDER_THREADS 15 //线程池 最大的个数

binder线程数目最大为15个。

二、实战案例分析

一起来看这个日志
在这里插入图片描述
很明显当时在做Binder通信,ANR发生在transcatNative函数中, transcatNative 函数式客户端发起端的函数。

说明这个ANR中的 客户端即有可能是在等Binder对端响应,我们知道Binder通信对于调用端来说是默认是阻塞等待响应,只有有了返回结果后才会继续执行下去。

这里就有两种情况:

  • 服务端调用方法时 发生了阻塞,导致客户端挂起。
  • Binder线程池超出了15个,导致无法继续分配,客户端挂起。

通过分析 发生anr的时候 cpu的状态,可以确定但是binder线程数是超过了15个,即可以确定是binder线程池限制导致。

为什么Binder线程池会造成ANR呢?

我们来设想下这种情况,A进程同时发起第16个binder请求后,由于没有C进程能够处理,因为此时线程池已经满了。
客户端发起的第16个binder请求此时就会处于阻塞状态。
在这里插入图片描述

更深层次一点讲 是其他进程给systemserver发送Binder消息时会被阻塞,因为没有对端binder线程。导致调用端需要等待结果,造成了ANR。

故问题的焦点, 在binder线程分配完毕,没有新线程分配,导致调用端在主线程挂起。
那还会有Binder造成ANR或异常的其他情况吗?
答案是有的。

Activity 传递数据 传1M时,造成了异常
Activity在异步时 传512k时 造成了异常
Binder Server服务端 复杂对象虚拟化造成ANR

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值