前言
相信各位大佬肯定在开发中遇到过这个问题:一顿操作猛如虎之后,总感觉程序有时候有点卡顿;或者自己自测得好好的,但是测试妹子的机器上却卡成狗。
那么,能不能做到运行APP之后,能自动地列出哪些类的哪些方法在主线程比较耗时呢?并且对原工程代码低侵入性或者零侵入性呢?
开源插件推荐
答案当然是肯定的,为了方便大家使用,这里我先列出来自己刚写的一个开源项目,专门监听Android主线程耗时方法。传送门:
Android耗时方法监听插件 MethodTimeMonitor
集成这个插件后,可以手动输入希望过滤的耗时时间,比如过滤出来主线程耗时200ms的方法,然后以包级目录结构的方式展示出来。
原理方案
首先,我们聊聊能实现需求的几种方案
- 定义基类,在基类中相关方法预留埋点代码
- Java动态代理
- 插桩技术
第一种方式我们可以直接pass掉,因为这样会对原工程造成非常高的倾入性,并且根本不能满足实现所有类在主线程的监听。这种方式只适合固定类的监听,比如监听所有Activity的生命周期。
第二种方式稍微靠谱,但是有一个致命缺点就是,动态代理只能代理接口,而不能代理实体类。并且同样不能满足所有类在主线程的监听。
第三种方式才是解决问题之道,也是我这篇文章的核心。
插桩技术
目前适用于Android的插桩技术有几个,比如笔者常用的有 ASM 和 Javassist。
Javassist 使用起来比较方便,使用语法都是 Java 形式的,库内部会自动转换为虚拟机指令。
ASM 的话使用起来就较为复杂,并且需要熟悉 JVM 虚拟机指令,然后通过虚拟机指令编程的方式进行插桩。但是复杂的使用换来的却是灵活的方式,因为你使用的是虚拟机指令,因此几乎你可以做到任何你想做到的事。不过想要把 ASM 玩出花来还需要很长的一段路要走,笔者也仅仅是停留在“会用”的阶段。
之前我有一系列的文章讲过 Javassist,因此这次这个库我采用的是 ASM 来实现的。对于 ASM 的使用,网上资料较少,大家最好去官网去阅读英文文档。因为不是本文重点,这里就不介绍 ASM 的使用了。