今天来分析下 Matrix 框架的 matrix-trace-canary 部分,相关文档可查看《 Matrix Android TraceCanary 》,这份文档是阅读源码的关键,强烈建议先看文档再读源码。java
TraceCanary 是检测应用卡顿的模块,在该模块下又细分了以下几个模块:android
在这些模块当中,又是依赖 MethodBeat 的提早插桩来达到检测的效果,因此,咱们在分析这几个模块以前,得先分析 MethodBeat 干了些什么,他是如何辅助以上几个模块来进行检测的。git
为了避免使文章变得枯燥无味,上面的四个模块会另起新的文章标题进行讲解,那么本文将会对 matrix-gradle-plugin 的插桩部分先进行一个大概的讲解,细节部分可能不会去分析,由于牵扯起来东西太多了。github
来看下文档中对编译插桩部分的描述:app
经过代理编译期间的任务 transformClassesWithDexTask,将全局 class 文件做为输入,利用 ASM 工具,高效地对全部 class 文件进行扫描及插桩。框架
插桩过程有几个关键点: 一、选择在该编译任务执行时插桩,是由于 proguard 操做是在该任务以前就完成的,意味着插桩时的 class 文件已经被混淆过的。而选择 proguard 以后去插桩,是由于若是提早插桩会形成部分方法不符合内联规则,无法在 proguard 时进行优化,最终致使程序方法数没法减小,从而引起方法数过大问题。函数
二、为了减小插桩量及性能损耗,经过遍历 class 方法指令集,判断扫描的函数是否只含有 PUT/READ FIELD 等简单的指令,来过滤一些默认或匿名构造函数,以及 get/set 等简单不耗时函数。工具
三、针对界面启动耗时,由于要统计从 Activity#onCreate 到 Activity#onWindowFocusChange 间的耗时,因此在插桩过程当中须要收集应用内全部 Activity 的实现类,并覆盖 onWindowFocusChange 函数进行打点。post
四、为了方便及高效记录函数执行过程,咱们为每一个插桩的函数分配一个独立 ID,在插桩过程当中,记录插桩的函数签名及分配的 ID,在插桩完成后输出一份 mapping,做为数据上报后的解析支持性能
apply plugin: 'om.tencent.matrix-plugin' 对应的是 matrix-gradle-plugin 中的MatrixPlugin 类:
implementation-class=com.tencent.matrix.plugin.MatrixPlugin
MatrixPlugin.java
该插件作了以下操做:
一、关联 apply MatrixPlugin 设置的 extensions 参数,该参数能够查看 sample 的 app build.gradle
二、插入 transfrom task,该 task 就如文档所描述的 transformClassesWithDexTask
三、移除未使用的资源文件
咱们进入 MatrixTraceTransform.inject 看看:
MatrixTraceTransform.java
successfully inject task:transformClassesWithDexBuilderForDebug
日志信息。
origTransform.transform(transformInvocation);
这个 origTransform 就是系统的 transformClassesWithDexBuilderForDebug
这时候,咱们能够直接来看 MatrixTraceTransform task 了, doTransfrom 是最重要的方法,这个部分我大概去讲解一下,由于涉及跳转太多,篇幅就会很是有影响,好在 Matrix 的开发者留给了咱们三个 step 注释,咱们就按照这三个步骤去解释:
一、step1:
这个地方须要关注几个 executor.submit 的执行,第一个 ParseMappingTask,这个 task 从名称上就能看出是一个解析 Mapping 的任务,这个任务作了以下的操做:
接着看 CollectDirectoryInputTask 和 CollectJarInputTask 任务,这两个任务主要收集 class 原文件和 traceClassOut 文件,class 原文件咱们都知道,就是扫描到的 class 文件,那 traceClassOut 文件是什么呢?在默认的配置中,会设置一份 traceClassOut 路径,这个配置路径指向的是 output/traceClassOut 路径,咱们能够打开 sample 下面的这个路径:
collectedClassExtendMap 集合中的数据是须要作插桩的类,该集合中的数据保存在 output/mapping/methodMapping 下面:
三、step3
拿到混淆类集合和还原的类集合,而后拿到在 step1 中收集到的原文件和 traceOut 文件,一并参与 trace 操做。所作的内容有:
补充部分:
整体的分析差很少了,但细节部分仍是须要去细扣,本人能力有限,不对之处还望指正。