当出现应用卡顿等性能问题时,如何通过查看 Binder 的运行时状态来诊断你的应用?本文将展示了一个简单实用的手段
0x00. 查看 Binder 实体运行状态
- 环境准备: 需要一台 Root 过的手机或模拟器。
- 执行命令: 输出数据量比较大,这里保存到一个文件中
Shell
adb shell cat /sys/kernel/debug/binder/state > binder.txt
- 分析重点: 在输出的巨量文本中,找到你正在开发的 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 主要是被谁在频繁调用。
- 专家行动: 可以去查一下 PID 1411 是哪个进程(通常是
0x03. 引用分析(Refs)------ 你持有了谁?
Ref 代表进程 3011 调用的远程接口(Proxy)。
-
句柄 0 (desc 0):
ref 30933: desc 0 node 1。这是标准的ServiceManager。 -
引用数量: 你拥有从
desc 0到desc 45的引用。- 专家视角: 45 个外部引用对于一个 App 进程来说是正常的。但如果
desc达到几百,说明你的 App 申请了太多的系统服务(如频繁获取 LocationManager, WindowManager 等)且没有释放,这会导致 系统服务端 出现内存泄漏。
- 专家视角: 45 个外部引用对于一个 App 进程来说是正常的。但如果
0x04. 内存缓冲区(Buffers)------ 风险核心
这是最硬核的部分,直接关联到 TransactionTooLargeException。
-
数据:
buffer 63164: size 144:0:0 delivered -
解析: *
144:0:0分别代表:数据大小 : 偏移量大小 : 死亡通知大小。- 这里的 Buffer 都很小(最大才 144 字节),且状态都是
delivered(已交付)。
- 这里的 Buffer 都很小(最大才 144 字节),且状态都是
-
预警信号: 如果你在排查卡顿或崩溃时,看到某个
buffer的size达到 500,000 以上(约 0.5MB),并且状态不是delivered而是长时间挂起,说明有一个大事务阻塞了 Binder 驱动,这会直接导致后续所有简单的 Binder 调用超时。
0x05. 寻找"幕后黑手"
- 从查询 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 进程交互。
- 思考: 为什么
node 63104只有ls 1 lw 1(本地强弱引用)而没有proc列表?
答:这通常意味着该对象刚创建或正在销毁,尚未被远程进程获取