说明:
1.该项目处在持续开发阶段,但可以在Debug 阶段使用,目前版本1.0.2 逐步完善中…
2.技术上讲不难实现,但是过程有不少坑
3.按照计划该项目分为两部分
Gradle 插件部分:就是该项目
Python 数据可视化部分:还未开始
用途
统计方法运行时间,效果如下
快速使用
1.在根项目build.gradle文件中添加我的maven仓库地址,并设置插件依赖
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
//1.我的maven 私有库地址
maven {
allowInsecureProtocol = true
url 'http://161.117.195.45:6677/repository/sand_repo/'
}
google()
mavenCentral()
maven { url 'https://dl.google.com/dl/android/maven2/' }
maven { url 'https://www.jitpack.io' }
jcenter()
maven { url 'https://jcenter.bintray.com' }
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.4"
classpath "com.sand.group:mt:1.0.2" //2.依赖插件
}
}
2.在app的build.gradle 中应用插件,并配置插件参数(MTConfig)
plugins {
id 'com.android.application'
id 'com.sand.mt'//应用插件
}
//MTConfig 配置的参数,供插件调用
MTConfig {
//配置自动生成MTCallBack类锁在的包路径
mtCallBackPackage="com.mt.autogen.callback"
//配置哪些包下面的类需要被插桩(这些包下面的方法都会被插桩)
//这样的配置意味着com.sand.apm.mtdemo包下面的类,除去黑名单,excludeClasses,excludeMethods
//的方法都会被插桩,如果某个类插桩后,运行时出现class not found
//请把它的类名添加到excludeClasses中
pkgs = [
"com.sand.apm.mtdemo"
]
whiteList = []//白名单这里的方法都插桩
blackList = []//黑名单这里的方法都不插桩
excludeMethods = [//这些方法都不插桩
"<init>", //构造方法不插桩
"<clinit>" //静态域的构造器不插桩
]
excludeClasses = [//这里的类都不需要插桩,直接写类文件名
"BuildConfig.class",
"Tool.class"
]
}
如果某个类插桩后,运行时出现class not found 请把它的类名添加到excludeClasses中
如果某个类插桩后,运行时出现class not found 请把它的类名添加到excludeClasses中
如果某个类插桩后,运行时出现class not found 请把它的类名添加到excludeClasses中
配置好这些参数后执行同步,make,不出意外的话,你将会在src/main/java 下面看到自动生成的代码。(如果一次不成功多试验几次,实在不行欢迎留言)
make 之后插件会在gradle.properties 文件中生成一个mt.work变量,如果你想关闭插件,配置其为false即可
------------------------分割线----------------------------
原理
利用gradle插件在编译后的class文件的方法调用开始和调用结束时候插入统计代码,实际效果如下
插桩前代码:
public static void method1(){
System.out.println("我是method1");
}
插桩后反编译代码
public static void method1() {
long currentTimeMillis = System.currentTimeMillis();
System.out.println("我是method1");
MTCallBack.mtDone(currentTimeMillis);
}
这里的MTCallBack是一个编译时动态生成的MTCallBack.Java文件,默认生成的代码如下,你可以在这个类里面写任何代码,比如收集App运行时的各种信息
public class MTCallBack{
public String tag="mt";
public static void mtDone(long start) {
long end = System.currentTimeMillis();
long cost = end - start;
StackTraceElement[] sts = Thread.currentThread().getStackTrace();
//sts[3] 就是mtDone被调用所在的方法,也可以循环向上查询更深的栈层级
String currentMethodName = sts[3].getClassName() + "." + sts[3].getMethodName();
String mtLog = currentMethodName + " 耗时:" + cost + " ms,Thread.name:" + Thread.currentThread().getName();
if (cost < 100) {
Log.w("mt",mtLog);
} else {
Log.e("mt",mtLog);
}
}
}
目前进度,存在的问题,未来计划
目前进度
已经在Windows上测试通过,Mac还没有来得及测试,预计很快完成
存在的问题
暂时只能在debug模式下使用(考虑到性能问题和确保App运行稳定),后期逐步完善
未来计划
我开发这个小插件的目的是替代Android Studio Profiler 火焰图的(因为我觉得火焰图看着不直观,而且有点麻烦,也不能进行多次数据对比),未来预计会朝着这个方向发展(数据更加直观方便,并丰富MTCallBack的默认功能)如果有兴趣参加这个小项目小伙伴欢迎留言 。
源码地址:https://github.com/woshiwzy/APM_MT