android studio编译,android 方法统计,Android 利用编译时 注入 统计App内所有方法执行时常,分析ANR

 2023-09-21 阅读 19 评论 0

摘要:Git传送门1.应用场景Android Studio提供了很多性能分析工具,分析CPU耗时,分析内存,但主要是给我们开发阶段使用,而且应用起来也不方便,如果我们能在APP运行的时候捕获所有方法的时间,然后取一些耗时排名前面的方法来做性能分析

Git传送门

1.应用场景

Android Studio提供了很多性能分析工具,分析CPU耗时,分析内存,但主要是给我们开发阶段使用,而且应用起来也不方便,如果我们能在APP运行的时候捕获所有方法的时间,然后取一些耗时排名

前面的方法来做性能分析,从而能更方便的排查一些性能的问提,或者将耗时统计统一提交到服务器,从而跟中不同机型

2.实现

android studio编译,这里用到的还是javassist,当然 AOP也可以实现我们的需求,关于javassist和AOP的实现都可以看前面的文章。  为什么这里用javassist,我们打包android程序的时候, gradle会通过javaCompileTask 或者kotlinCompileTask编译成class文件,存储到build\intermediates\javac  或者build\tmp\kotlin-classes 目录下,此时 如果你使用aspectj  它会直接修改 当前编译后存储的文件,然后gradle通过 一个个*transform* Task,  transform 可能会有很多,前一个transform 的输入就是后一个的输出,第一个输入一般就是前面的路径, 最后会经过一个dexTransform  打包成一个个dex,再合成一个或几个大的dex。 用javassist来实现注入的话可以保证执行顺序放在最后一个transform修改上。

关于transform的介绍 可以看前面那个捕获第三方库异常的  这里主要看下核心代码

不知道是不是因为编译的原因, 我这里试了下新建个本地变量,但如果碰到方法只有while的时候 insert会被插入到while里面,所以直接在类里查了个静态变量

CtField ctField = newCtField(CtClass.longType,param,c)

ctField.setModifiers(9)

c.addField(ctField,"0l")

apk注入,javassist里面modifiers主要是标识修饰符,可以通过不同的拼凑  public 是1,static是8 所以这里静态变量设了9,因为用到的是System.currentTimeMillis 直接射了一个long的变量

public static final int PUBLIC = AccessFlag.PUBLIC;

public static final int PRIVATE = AccessFlag.PRIVATE;

public static final int PROTECTED = AccessFlag.PROTECTED;

public static final int STATIC = AccessFlag.STATIC;

public static final int FINAL = AccessFlag.FINAL;

手机上编译android源码、public static final int SYNCHRONIZED = AccessFlag.SYNCHRONIZED;

public static final int VOLATILE = AccessFlag.VOLATILE;

public static final int VARARGS = AccessFlag.VARARGS;

public static final int TRANSIENT = AccessFlag.TRANSIENT;

public static final int NATIVE = AccessFlag.NATIVE;

public static final int INTERFACE = AccessFlag.INTERFACE;

Android9编译系统、public static final int ABSTRACT = AccessFlag.ABSTRACT;

public static final int STRICT = AccessFlag.STRICT;

public static final int ANNOTATION = AccessFlag.ANNOTATION;

public static final int ENUM = AccessFlag.ENUM;

直接插入打印方法从开始到结束的时间,这里本来想直接用insertAfter,但发现在复杂项目里一直报错,定位不到具体错误,就改成了插入具体行

String line = " System.out.println(\""+c.getName()+"::::"+m.getMethodInfo().getName()+"======= \"+(System.currentTimeMillis() - "+param+"));"

androidsql防注入、try{

int lineNum = 0;

if(m.getReturnType().getName().contains("void")) {

lineNum = m.getMethodInfo().getLineNumber(m.getMethodInfo().codeAttribute.length())

}else {

lineNum = m.getMethodInfo().getLineNumber(m.getMethodInfo().codeAttribute.length()) -1

安卓注入js、}

if(lineNum>0)

m.insertAt(lineNum,line)

}catch(CannotCompileException ex){

System.out.println(param+" get Error")

}

Android10源码编译、下面是原有代码

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

fillListRight();

// var test = TestFile()

为什么要编译Android源码。// test.string

}

private fun fillListRight() {

list.forEach {

Log.e("lin","list="+it);

Thread.sleep(500)

ffmpeg android编译?}

}

下面是log中打印的日志, 可以看到onCreate执行了 1592mm,fillListRight执行了1503mm,demo中只有一个类,如果在复杂项目中,跑一遍流程,然后定位出耗时方法,从而能辅助我们找到一些可能造成ANR的方法

下面是反编译 MainActivity的结果, 在方法执行前后 插入了 打印耗时的代码  具体代码可以看从git上获取

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/1/81499.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息