美文网首页
ASM字节码插桩实现点击防抖

ASM字节码插桩实现点击防抖

作者: HarryChen | 来源:发表于2021-08-09 21:59 被阅读0次

    关于gradle plugintransform之前的文章说过了,这里就不展开说了
    思路:在点击事件onclick的时候,将view的onclick在给定的时间给拦截掉。以前我们可能都是用一个util来拦截,这样在每个点击事件都得去判断,那么这里就用字节码插桩的形式来实现一下。

    ASM的引入

    dependencies {
        implementation gradleApi()
        implementation localGroovy()
        //常用io操作
        implementation "commons-io:commons-io:2.6"
    
        // Android DSL  Android编译的大部分gradle源码
        implementation 'com.android.tools.build:gradle:3.6.2'
        implementation 'com.android.tools.build:gradle-api:3.6.2'
        //ASM
        implementation 'org.ow2.asm:asm:7.1'
        implementation 'org.ow2.asm:asm-util:7.1'
        implementation 'org.ow2.asm:asm-commons:7.1'
    }
    复制代码
    

    常用的对象

    • ClassReader : 按照Java虚拟机规范中定义的方式来解析class文件中的内容,在遇到合适的字段时调用ClassVisitor中相应的方法

    • ClassVisitor : Java中类的访问者,提供一系列方法由ClassReader调用.它是一个抽象类,在使用时需要继承此类.

    • ClassWriter : 它是一个继承了ClassVisitor的类,主要负责将ClassReader传递过来的数据写到一个字节流中.在传递数据完成之后,可以通过它的toByteArray方法获得完整的字节流.

    • ModuleVisitor : Java中模块的访问者,作为ClassVisitor.visitModule方法的返回值,要是不关心模块的使用情况,可以返回一个null.

    • AnnotationVisitor : Java中注解的访问者,作为ClassVisitor.visitTypeAnnotation的返回值,不关心注解使用情况也是可以返回null.

    • FieldVisitor : Java中字段的访问者,作为ClassVisitor.visitField的返回值,不关心字段使用情况也是可以返回null.

    • MethodVisitor:Java中方法的访问者,作为ClassVisitor.visitMethod的返回值,不关心方法使用情况也是可以返回null

    ASM工作流程

    通过ClassReader读取class字节码文件,然后ClassReader将读取到的数据通过一个ClassVisitor(上面的ClassWriter其实就是一个ClassVisitor)将数据表现出来.表现形式: 将字节码的每个细节按顺序通过接口的方式传递给ClassVisitor.就比如说,访问到了class文件的xx方法,就会回调ClassVisitor的visitMethod方法;访问到了class文件的属性,就会回调ClassVisitor的visitField方法.

    ClassWriter是一个继承了ClassVisitor的类,它保存了这些由ClassReader读取出来的字节流数据,最后通过它的toByteArray方法获得完整的字节流

    具体代码

    主要技术点: Gradle plugin + transform + annotation + ASM

    • Gradle plugin
    plugin.jpg
    • Gradle transform

    [图片上传失败...(image-16cf10-1628517507917)]

    process.jpg
    • annotation
    annotation.jpg
    • ASM
    classvisit.jpg method.jpg asset.jpg shouldclick.jpg

    代码测试

    testcode.jpg

    反编译查看

    result1.jpg result2.jpg result3.jpg

    可以看到,正常的onclick写法是可以插桩成功,添加注解时可以成功跳过插桩的,lamda表达式这种情况下是无法插桩成功的,生成的class方法名上没有onclick标志,找不到什么共同点,这个暂时没有想到什么好的办法,但是现在基本都是kotlin代码了,所以这种形式感觉还是有些鸡肋了。
    项目源码

    相关文章

      网友评论

          本文标题:ASM字节码插桩实现点击防抖

          本文链接:https://www.haomeiwen.com/subject/pdetbltx.html