深入解析 Binder 运行的状态

当出现应用卡顿等性能问题时,如何通过查看 Binder 的运行时状态来诊断你的应用?本文将展示了一个简单实用的手段

0x00. 查看 Binder 实体运行状态

  1. 环境准备: 需要一台 Root 过的手机或模拟器。
  2. 执行命令: 输出数据量比较大,这里保存到一个文件中
Shell 复制代码
adb shell cat /sys/kernel/debug/binder/state > binder.txt
  1. 分析重点: 在输出的巨量文本中,找到你正在开发的 App PID(本文PID=3011)。
  • proc 节点:它开了多少个线程(threads)?
  • nodes:它暴露了多少个 Binder 实体(服务)给别人用?
  • refs:它引用了多少个远程服务?

输出的 binder.txt 内容实在太大,这里只展示PID:3011(包名为com.android.launcher3)的binder 运行状态

shell 复制代码
proc 3011
context binder
  thread 3011: l 00 need_return 0 tr 0
  thread 3060: l 12 need_return 0 tr 0
  thread 3061: l 11 need_return 0 tr 0
  thread 3062: l 11 need_return 0 tr 0
  thread 3136: l 00 need_return 0 tr 0
  thread 3196: l 00 need_return 0 tr 0
  thread 3198: l 00 need_return 0 tr 0
  thread 3203: l 11 need_return 0 tr 0
  thread 3209: l 00 need_return 0 tr 0
  thread 3210: l 00 need_return 0 tr 0
  node 30941: ub400006dcd0c4b20 cb400006dfd0981d0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 31046: ub400006dcd0d70f0 cb400006dfd0988f0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 33583: ub400006dcd0f07a0 cb400006dfd0ac930 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 63104: ub400006dcd0f2060 cb400006e2d120db8 pri 0:139 hs 1 hw 1 ls 1 lw 1 is 0 iw 0 tr 1
  node 33482: ub400006dcd0f4f40 cb400006ded0b0d30 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 581
  node 32258: ub400006dcd0f7cd0 cb400006dfd09ee30 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 2 iw 2 tr 1 proc 2643 1411
  node 32218: ub400006dcd0f7d60 cb400006dfd0a06f0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 32256: ub400006dcd0f7e80 cb400006dfd09fcd0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 32262: ub400006dcd0f7eb0 cb400006dfd0969d0 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 32295: ub400006dcd0f7ee0 cb400006dfd09f310 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 32308: ub400006dcd0f8120 cb400006dfd09f370 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 32091: ub400006dcd0f8240 cb400006dfd09f010 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  node 31614: ub400006dcd102d10 cb400006dfd09e950 pri 0:139 hs 1 hw 1 ls 0 lw 0 is 1 iw 1 tr 1 proc 1411
  ref 30933: desc 0 node 1 s 1 w 1 d 0000000000000000
  ref 30936: desc 1 node 3466 s 1 w 1 d 0000000000000000
  ref 30955: desc 2 node 2917 s 1 w 1 d 0000000000000000
  ref 30956: desc 3 node 2714 s 1 w 1 d 0000000000000000
  ref 30957: desc 4 node 4037 s 1 w 1 d 0000000000000000
  ref 30958: desc 5 node 8172 s 1 w 1 d 0000000000000000
  ref 30959: desc 6 node 3446 s 1 w 1 d 0000000000000000
  ref 30960: desc 7 node 4200 s 1 w 1 d 0000000000000000
  ref 30962: desc 8 node 4418 s 1 w 1 d 0000000000000000
  ref 30963: desc 9 node 3462 s 1 w 1 d 0000000000000000
  ref 30964: desc 10 node 4150 s 1 w 1 d 0000000000000000
  ref 30965: desc 11 node 4205 s 1 w 1 d 0000000000000000
  ref 30966: desc 12 node 4519 s 1 w 1 d 0000000000000000
  ref 30967: desc 13 node 2775 s 1 w 1 d 0000000000000000
  ref 30968: desc 14 node 6037 s 1 w 1 d 0000000000000000
  ref 30969: desc 15 node 4041 s 1 w 1 d 0000000000000000
  ref 30970: desc 16 node 4411 s 1 w 1 d 0000000000000000
  ref 30971: desc 17 node 8081 s 1 w 1 d 0000000000000000
  ref 30972: desc 18 node 4124 s 1 w 1 d 0000000000000000
  ref 30973: desc 19 node 2860 s 1 w 1 d 0000000000000000
  ref 30974: desc 20 node 5801 s 1 w 1 d 0000000000000000
  ref 30975: desc 21 node 4878 s 1 w 1 d 0000000000000000
  ref 30992: desc 22 node 30991 s 1 w 1 d 0000000000000000
  ref 30994: desc 23 node 30993 s 1 w 1 d 0000000000000000
  ref 31597: desc 24 node 571 s 1 w 1 d 0000000000000000
  ref 31601: desc 25 node 31600 s 1 w 1 d 0000000000000000
  ref 31819: desc 26 node 31818 s 1 w 1 d 0000000000000000
  ref 31757: desc 27 node 2168 s 1 w 1 d 0000000000000000
  ref 31771: desc 28 node 999 s 1 w 1 d 0000000000000000
  ref 31989: desc 29 node 9401 s 1 w 1 d 0000000000000000
  ref 31991: desc 30 node 31990 s 1 w 1 d 0000000000000000
  ref 32266: desc 31 node 32265 s 1 w 1 d 0000000000000000
  ref 32270: desc 32 node 32269 s 1 w 1 d 0000000000000000
  ref 32339: desc 33 node 32338 s 1 w 1 d 0000000000000000
  ref 32569: desc 34 node 8313 s 1 w 1 d 0000000000000000
  ref 32577: desc 35 node 8319 s 1 w 1 d 0000000000000000
  ref 33004: desc 36 node 32318 s 1 w 1 d 0000000000000000
  ref 33005: desc 37 node 32981 s 1 w 1 d 0000000000000000
  ref 33006: desc 38 node 32983 s 1 w 1 d 0000000000000000
  ref 33023: desc 39 node 18749 s 1 w 1 d 0000000000000000
  ref 78180: desc 40 node 78169 s 1 w 1 d 0000000000000000
  ref 61925: desc 41 node 61900 s 1 w 1 d 0000000000000000
  ref 33739: desc 42 node 33725 s 1 w 1 d 0000000000000000
  ref 33740: desc 43 node 33710 s 1 w 1 d 0000000000000000
  ref 33858: desc 44 node 25540 s 1 w 1 d 0000000000000000
  ref 33859: desc 45 node 33759 s 1 w 1 d 0000000000000000
  buffer 33519: 0000000000000000 size 8:0:0 delivered
  buffer 63108: 0000000000000000 size 0:0:0 delivered
  buffer 32963: 0000000000000000 size 36:0:0 delivered
  buffer 63164: 0000000000000000 size 144:0:0 delivered

0x01. 线程池状态分析(Threads)

这里列出了 10 个线程(从 3011 到 3210)。

  • 关键数据: l 值(代表 looper 状态)。

    • l 11 (BC_REGISTER_LOOPER) 和 l 12 (BC_ENTER_LOOPER) 表示这些线程是 Binder 工作线程
    • thread 3060, 3061, 3062, 3203 这四个线程目前处于 Ready 状态,等待任务。
  • 专家视角: * 健康度: 10 个线程远未达到默认的 15 个上限,说明该进程目前没有 Binder 线程饥饿问题。

    • 主线程: thread 3011 是主线程(PID=TID),它的 tr 0 表示目前没有正在进行的 Binder 事务。如果这里 tr 长期不为 0,说明主线程被 Binder 调用卡住了(即常见的 ANR 隐患)。

0x02. Binder 实体分析(Nodes)------ 你暴露了什么?

Node 代表进程 3011 提供的接口(Stub)。

  • 多端引用: 看到 node 32258 后面跟着 proc 2643 1411

    • 这说明进程 2643 和 1411 都在持有并可能调用 3011 的同一个接口。
  • 跨进程足迹: 3011 暴露的 Node 大部分被 PID 1411 引用。

    • 专家行动: 可以去查一下 PID 1411 是哪个进程(通常是 system_server 或关键系统 UI 进程)。这能帮你理清你的 App 主要是被谁在频繁调用。

0x03. 引用分析(Refs)------ 你持有了谁?

Ref 代表进程 3011 调用的远程接口(Proxy)。

  • 句柄 0 (desc 0): ref 30933: desc 0 node 1。这是标准的 ServiceManager

  • 引用数量: 你拥有从 desc 0desc 45 的引用。

    • 专家视角: 45 个外部引用对于一个 App 进程来说是正常的。但如果 desc 达到几百,说明你的 App 申请了太多的系统服务(如频繁获取 LocationManager, WindowManager 等)且没有释放,这会导致 系统服务端 出现内存泄漏。

0x04. 内存缓冲区(Buffers)------ 风险核心

这是最硬核的部分,直接关联到 TransactionTooLargeException

  • 数据: buffer 63164: size 144:0:0 delivered

  • 解析: * 144:0:0 分别代表:数据大小 : 偏移量大小 : 死亡通知大小

    • 这里的 Buffer 都很小(最大才 144 字节),且状态都是 delivered(已交付)。
  • 预警信号: 如果你在排查卡顿或崩溃时,看到某个 buffersize 达到 500,000 以上(约 0.5MB),并且状态不是 delivered 而是长时间挂起,说明有一个大事务阻塞了 Binder 驱动,这会直接导致后续所有简单的 Binder 调用超时。

0x05. 寻找"幕后黑手"

  1. 从查询 PID
shell 复制代码
adb shell ps -A | grep 1411                                                        

system 1411 851 16778868 399132 do_epoll_wait 0 S system_server

Shell 复制代码
adb shell ps -A | grep 2643                                                        

u0_a118 2643 851 13886788 123388 do_epoll_wait 0 S com.android.inputmethod.latin

shell 复制代码
adb shell ps -A | grep 581                                                         

system 581 1 11133444 43892 do_epoll_wait 0 S surfaceflinger

可以发现这个进程(com.android.launcher3)主要是跟 system_server、输入法、surfaceflinger 进程交互。

  1. 思考: 为什么 node 63104 只有 ls 1 lw 1(本地强弱引用)而没有 proc 列表?
    答:这通常意味着该对象刚创建或正在销毁,尚未被远程进程获取
相关推荐
2501_915106327 小时前
iOS App 测试方法,通过 Xcode、Instruments、Safari Inspector、克魔(KeyMob)等工具
android·ios·小程序·uni-app·iphone·xcode·safari
游戏开发爱好者87 小时前
对 iOS IPA 文件进行深度混淆的一种实现路径
android·ios·小程序·https·uni-app·iphone·webview
成都大菠萝7 小时前
2-2-5 快速掌握Kotlin-语言的泛型函数
android
成都大菠萝7 小时前
2-2-4 快速掌握Kotlin-定义泛型类
android
掘我的金7 小时前
加载状态优化实践:如何让用户始终知道当前状态
android
成都大菠萝7 小时前
2-2-6 快速掌握Kotlin-语言的多泛型参数学习
android
掘我的金7 小时前
空状态优化实践:如何让"白屏"变成友好的提示
android
_李小白7 小时前
【Android FrameWork】第三十四天:系统设置项(Settings)与系统属性(System Properties)
android·jvm·oracle
、BeYourself8 小时前
GridLayoutManager 网格布局与 RecyclerView 拖拽侧滑实战
android·android-studio