APM之实现篇

在前文中已经详细介绍了APM的android端的原理,接下来会通过代码实现记录某类异常日志这个小功能来深入理解APM的实现原理。场景如下,记录所有捕获的IndexOutOfBoundsException。前文中提到,APM一般分为3个部分,plugin、agent和具体的业务代码。本文也将会按这三个分类来介绍。
注:由于篇幅有限,本文所展示的只有部分关键代码,有兴趣的可自行阅读github上的源码

  • 业务代码
    我们的业务场景很简单,只需提供一个处理异常的方法就足够了。
public static void pushException(Throwable th){
    //在这里处理异常,如打印或上传日志
}
  • agent
    agent是最复杂的一个部分。它最终要达到的目的就是改写dexer.Main,在它执行processClass方法内的代码之前通过ASM工具修改第二个参数,即源class文件的byte数组。如果这个class的某个方法中包含了捕获IndexOutOfBoundsException的try-catch代码块,我们将在catch内调用上面的pushException方法。然后将这个修改过后的类对应的byte数组再替换回去。
    首先说明,字节码是通过异常表来处理异常的,有兴趣的可以通过字节码查看工具来查看异常表长什么样子。大概就是表里面每行记录都定义了如果代码在start行到end行之间抛出了异常,那么将转到handle行进行处理。这里的start到end就相当于try到catch之间的代码,而handle就是catch内开始的代码。查看ASM文档,AdviceAdapter中的visitTryCatchBlock和visitLabel这两个方法正好能满足我们的需求。只需要在visitTryCatchBlock方法中记录目标exception处理的handle,然后,如果在visitLabel中传入的正是我们刚才记录的handle,则加上调用pushException方法的代码。
public class ExceptionLogMethodAdapter extends AdviceAdapter {
   
    private TransformContext context;
    //记录所有目标exception的handle
    //key为handle,value是此handle对应的exception。
    //注:一个catch可能包含了多个exception,
    //如catch(IndexOutOfBoundsException | Exception e)
    private HashMap<Label, ArrayList<String>> matchedHandle = new HashMap<>();

    protected ExceptionLogMethodAdapter(TransformContext context
            , MethodVisitor methodVisitor, int access, String name, String desc) {
        super(Opcodes.ASM5, methodVisitor, access, name, desc);
        this.context = context;
    }

    @Override
    public void visitTryCatchBlock(Label start, Label end, Label handle,
                                   String exception) {
        //目标exception,在本文中为java/lang/IndexOutOfBoundsException
        HashSet<String> targetException = context.getExceptions();
        if (exception != null && targetException.contains(exception)) {
            context.getLog().d("find exception " + exception);
            ArrayList<String> handles = matchedHandle.get(handle);
            if
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值