Android 性能优化与分析工具
#Profiler#Perfetto#LeakCanary#Coroutine
← 学习资料优先级:核心
核心原理讲解
Android Profiler 怎么用?
在 AS 里,Profiler 主要分 CPU、Memory、Network 三大面板。
- CPU Profiler:用来找卡顿和方法耗时。一般用 Sampled(抽样)模式 抓一段 Trace,生成火焰图(Flame Chart)。火焰图里越宽的方块代表这个方法执行时间越长,我们可以顺着它一层层往下看,找出最底层的耗时热点。

- Memory Profiler:用来排查内存抖动和泄漏。在里面可以直接看实时分配的对象。如果发现内存曲线呈“锯齿状”高频起伏,说明有内存抖动(短时间内高频创建并销毁大对象,比如在
onDraw里 new 对象或频繁拼接 String),这会引发高频 GC 导致卡顿。
Perfetto / Systrace 的读图思路
它们是系统级的性能分析工具,基于 Linux 内核的 ftrace 机制。
- 怎么读图:抓出来的 Trace 是一个多轨时间线视图。首先看 UI Thread 和 RenderThread。如果发现某一帧超过了 16.6ms(60Hz)或 11.1ms(90Hz),对应的 Frame 轨道就会标红。
- 然后看主线程这一帧里在干什么。如果阻塞在
monitor contention(锁竞争)或进程间的 Binder 调用(binder transaction),那主线程就会被挂起(处于 Blocked 状态),这就是导致卡顿的真凶。如果是Choreographer#doFrame下面的performTraversals(绘制三大流程)耗时过长,说明是布局太深或自定义 View 绘制太重。

LeakCanary 的检测原理
可以用一句话概括:弱引用关联引用队列 + 主动 GC 校验。

- 自动检测销毁:LeakCanary 注册了 Activity 和 Fragment 的生命周期监听。当它们执行
onDestroy时,LeakCanary 会把这个销毁的对象包装成一个WeakReference(弱引用),并关联一个ReferenceQueue(引用队列)。 - 触发检测:过 5 秒钟后,系统会收到检测通知。它先通过 GC 机制让对象去回收,然后检查
ReferenceQueue。 - 判断泄漏:如果该对象的弱引用没有出现在
ReferenceQueue里,说明这个已经被销毁的对象仍然被外界强引用着,判定为内存泄漏。 - 生成引用链:判定泄漏后,LeakCanary 会在后台进程进行
Heap Dump生成.hprof文件,利用 Shark 库分析堆内存,计算出泄漏对象到 GC Root 的最短路径引用链。
协程内存泄漏的常见模式
协程是用户态的,但它的挂起点是通过 Continuation(状态机)保存在堆上的。
如果一个协程的 CoroutineScope 生命期太长(比如滥用 GlobalScope 或把协程跑在了一个没有随 Activity/ViewModel 销毁而 cancel 的 Scope 里),那么这个挂起的协程就会一直留在内存中。它所持有的所有局部变量、外部类引用(比如 Activity 里的 UI 控件、ViewModel 实例)都会被这个 Continuation 强引用着,从而导致严重的内存泄漏。
工程注意事项
-
[!IMPORTANT] 网络库配置细节:取消网络请求并不等于立即关闭连接池中的 TCP 连接。对于仍可复用的连接,OkHttp 会将其保留在连接池中,等待后续请求复用;连接最终何时释放,取决于连接状态、服务端响应和连接池配置。
-
[!WARNING] GC 机制防坑:很多人以为调用
System.gc()对象就会立刻回收。实际上,System.gc()只是向 JVM 建议进行一次 Full GC,至于系统什么时候真的执行、回不回收,是不可控的。LeakCanary 底层也是先通过多次触发 GC 建议,再等待数秒,才去确认弱引用是否被真正回收。