epic hook性能监控
Epic 是一个在虚拟机层面、以 Java Method 为粒度的运行时AOP Hook 框架。简单来说,Epic 就是 ART 上的Dexposed(支持 Android 5.0 ~ 11)。它可以拦截本进程内部几乎任意的 Java 方法调用,可用于实现AOP 编程、运行时插桩、性能分析、安全审计等。Epic:GitHub - tiann/epic: Dynamic java method AO
Epic 是一个在虚拟机层面、以 Java Method 为粒度的 运行时 AOP Hook 框架。简单来说,Epic 就是 ART 上的 Dexposed(支持 Android 5.0 ~ 11)。它可以拦截本进程内部几乎任意的 Java 方法调用,可用于实现 AOP 编程、运行时插桩、性能分析、安全审计等。
目前可以监控的场景如:Handler消息处理的耗时;Thread线程的执行时长;Activity的各生命周期耗时;ImageView中设置的图片大小检查;Binder进程间通信耗时;dex文件的加载等场景。
优点:无侵入性,代码编写简单、易懂。
实战:针对***可以使用epic的0.3.6版本,项目引入 api ("me.weishu:epic:0.3.6")
1、Handler消息处理的耗时:
hook两个方法:一个是sendMessageAtTime,这样我们就可以知道发生message的一个堆栈
另外一个是dispatchMessage方法。
因为对于发送message,不管调用哪个方法最终都会调用到一个是sendMessageAtTime这个方法,而处理message呢,它最终会调用dispatchMessage方法。
|
注入Hook:
|
如图为一些检测到的耗时操作:
2、Thread线程的执行时长:
Thread有2个AOP点:我为Dexposed续一秒——论ART上运行时 Method AOP实现 | Weishu's Notes
其一是 Thread.class 的run方法,拦截这个方法,我们可以知道所有通过Thread类本身创建的线程。hook线程的run方法:DexposedBridge.findAndHookMethod(Thread.class, "run", new ThreadMethodHook());打印前后的执行时差。
其二是Thread的构造函数,这个Hook点我们可以知道运行时具体有哪些类继承了Thread.class类,在找到这样的子类之后,直接hook掉这个类的run方法,从而达到了拦截所有线程创建的目的。
如图为检测到的一些线程创建、销毁、耗时等:
3、ImageView中设置的图片大小检查:
针对普通ImageView:
通过查看ImageView的源码我们可以看到setImageResource、setImageURI、setImageDrawable这些设置图片的方法都会调用到updateDrawable方法,在该方法内我们可以获取到转化好的Drawable对象,即可拿到被设置的图片的宽高信息,和imageView控件的宽高做对比即可,超过阈值则打印相关log。
针对项目中的ImageTile:
思路同上,hook点为updateDrawable。
|
在ImageHook中,进行图片和view的宽高检查即可。
目前设置的为1.2倍,项目中有较多的不合理尺寸的图片,
如图为检测到的不合理的图片:
4、Activity的各生命周期耗时:
思路一:拿到项目中的所有自己的 XXX_Activity 进行hook的注册,然后针对onCreate、onStart、onResume方法的执行时间监控。
我们的项目是多dex,目前只拿到了主dex中的activity,未解决:需拿到所有dex,并找出所有XXX_activity。
思路二:可以hook住Android的 Activity ,根据activity两个生命周期的差值计算各个生命周期的耗时。
例如onCreate的耗时计算为:onStart开始时间 - onCreate开始时间,
存在问题:1、onResume的执行时间无法计算;2、可能混杂了系统的其他时间,因为onStart开始时间 - onCreate开始时间,之间会混有系统其他函数的执行时间,非纯onCreate时间。
如下图为思路二获取到的activity的onCreate+onStart的耗时时长:
思路三:模仿ARouter,添加注解,在编译期扫描所有标注过的Activity,然后监听耗时
思路四:在application和activity的所有生命周期调用中,都会先调用instrumentation的相应方法。Instrumentation的理解 - 简书
因此只需要hook其中的callActivityOnCreate,callApplicationOnCreate,newActivity,callActivityOnNewIntent 等方法,即可获取到精确的各个生命周期的耗时。
此种方式精确并且简单易行,项目中建议使用这个方式。如下图为打印出来的各个生命周期的耗时:
5、Binder进程间的通信耗时:
对android.os.BinderProxy类的transact方法进行Hook。
如下一些打印出来的binder耗时:
更多推荐
所有评论(0)