21、Binder 的调试与优化:使用 dumpsys、binder_stats、binder_trace 进行问题定位
Binder 这玩意儿,平时跑得好好的,一出问题就让人头大。死锁、卡顿、服务挂掉……我见过太多同事对着 logcat 发呆,半天找不到根因。
其实,Android 系统早就给我们准备了三把利器:dumpsys、binder_stats、binder_trace。用好它们,Binder 问题基本无处遁形。
今天我就把这几个工具怎么用、怎么看、怎么定位问题,一次性讲清楚。
一、dumpsys:Binder 的“体检报告”
dumpsys 是 Android 系统最强大的诊断命令之一。我个人习惯,遇到 Binder 相关异常,第一件事就是跑 dumpsys binder。
1.1 查看 Binder 节点状态
adb shell dumpsys binder --binder
这条命令会输出当前系统中所有 Binder 节点的信息。包括:
- 每个 Binder 实体的引用计数
- 本地和远程的强/弱引用数量
- 死亡通知的注册情况
我在项目中遇到过一个问题:某个服务频繁崩溃,但 log 里没有任何异常。跑了一遍 dumpsys binder,发现某个 Binder 节点的引用计数异常高——有个模块忘记释放引用,导致服务无法正常销毁。
refs:当前引用数deathRecipients:注册的死亡通知数localBinder:本地 Binder 对象地址
1.2 查看 Binder 线程池
adb shell dumpsys binder --threads
Binder 线程池默认有 16 个线程。如果所有线程都被占满,新的 Binder 调用就会阻塞。
我曾经排查过一个 ANR 问题,用这条命令发现 16 个线程全部处于 waiting 状态——都在等同一个锁。说白了,就是死锁了。
| 线程状态 | 含义 |
|---|---|
| WAITING | 线程空闲,等待任务 |
| RUNNING | 正在处理 Binder 调用 |
| BLOCKED | 被锁阻塞,可能死锁 |
二、binder_stats:Binder 调用的“流量监控”
binder_stats 在 /proc/binder/stats 里。它能告诉你每个进程的 Binder 调用情况。
2.1 查看进程级统计
adb shell cat /proc/binder/stats
输出内容大致如下:
proc 1234
threads: 8
requested threads: 0
ready threads: 8
free async space: 524288
transactions: 1024
pending: 0
这里我最关注两个指标:
- transactions:该进程发起的 Binder 事务总数。如果增长过快,说明有频繁的跨进程调用。
- pending:等待处理的事务数。如果这个值持续不为 0,说明处理速度跟不上请求速度。
2.2 查看事务类型分布
adb shell cat /proc/binder/transactions
这个文件会列出当前所有未完成的 Binder 事务。包括:
- 事务的发起方和接收方
- 事务的代码(code)
- 事务的状态(active/complete)
嗯,这里要注意:如果某个事务长时间处于 active 状态,那基本可以断定它卡住了。
三、binder_trace:Binder 的“黑匣子”
binder_trace 是内核提供的 Binder 事件追踪机制。它能记录每一次 Binder 调用的完整生命周期。
3.1 开启 Binder 追踪
adb shell echo 1 > /sys/kernel/debug/tracing/events/binder/enable
adb shell cat /sys/kernel/debug/tracing/trace_pipe
这样就能实时看到 Binder 调用的日志了。每条日志包含:
- 事务 ID
- 发起进程和线程
- 目标进程和线程
- 事务的 code 和 flags
- 耗时(从发起到底层驱动处理完成)
3.2 分析典型问题
举个例子。我曾经遇到一个 ANR,log 里只看到 Waiting for binder transaction。开启 binder_trace 后,发现某个事务的耗时高达 5 秒——目标进程在做一个耗时的文件操作,把 Binder 线程给堵死了。
四、核心知识体系
下面这张图,是我总结的 Binder 调试三板斧。你想想看,遇到问题先对号入座,能省不少时间。
五、实战:一个完整的排查案例
我记得有一次,系统服务 SurfaceFlinger 频繁 ANR。log 里只有一句:
W/ActivityManager: ANR in com.android.systemui (SurfaceFlinger)
Reason: Waiting for binder transaction
我按顺序排查:
- dumpsys binder --threads:发现 SurfaceFlinger 的 16 个 Binder 线程全部 WAITING。
- cat /proc/binder/transactions:发现有一个事务处于 active 状态,已经持续了 3 秒。
- 开启 binder_trace:看到这个事务的目标进程是某个第三方应用,code 是
TRANSACTION_SCREENSHOT。
真相大白:那个第三方应用在截图时,做了大量的 Bitmap 处理,占用了 Binder 线程不放。SurfaceFlinger 想发新事务,只能排队等着。
六、避坑指南
我曾经踩过几个坑,分享给你:
- 不要只看 logcat:Binder 问题很多时候 logcat 里只有一句“Waiting for binder transaction”,根本看不出根因。必须结合内核层的工具。
- binder_trace 别开太久:它会产生大量日志,容易把磁盘写满。我一般只开 10 秒,抓到关键信息就关。
- 注意权限:有些设备需要 root 才能访问
/proc/binder/下的文件。没有 root 的话,可以用dumpsys替代部分功能。
好了,Binder 调试三板斧就讲到这里。下次遇到 Binder 问题,别慌,按这个流程走一遍,基本都能找到根因。