ASM

2021-02-14  本文已影响0人  Drew_MyINTYRE

ASM 是什么?

ASM 是一个十分强大的字节码处理框架,基本上可以实现对字节码的任何操作,但是需要对 Java 字节码有一定了解,ASM 可以通过操作指令码来生成字节码或者插桩,利用 ASM 的 API 来操控字节码时,就有很大的自由度来进行各种字节码的生成、修改、操作等等。ASM 只负责操作字节码,我们还需要通过自定义 gradle plugin 的形式来干预编译过程,在编译过程中获取到所有的class 文件和 jar 包,然后遍历他们,利用 ASM 来修改字节码,达到插桩的目的。

Java 文件通过 javac 编译后会生成十六进制的 class 字节码文件,这一堆十六进制数是按严格的结构拼接在一起的,按顺序分别是:魔数(cafe babe)、java 版本号、常量池、访问权限标志、当前类索引、父类索引、接口索引、字段表、方法表、附加属性等十个部分,这些部分以十六进制的形式表达出来并紧凑的拼接在一起。这个十六进制文件显然不具备可阅读性,所以我们可以通过 javap -verbose Test 来反编译,有兴趣的可以自己试一试。借助 010 Editor,可以帮助我们较为清晰的看到 class 文件每一部分的结构,直接拖动你的 class 文件到 010 Editor 即可查看。

// 编译成 class 文件
javac Hello.java

ls -l *.class

rm *.class

// 反编译 class 文件
javap Hello.class

// 查看字节码
javap -verbose Hello.class

// Run Hello.java
java Hello

类型描述符

方法描述符

(参数类型描述符)返回值描述符

// 例如:
boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) 

(Landroid/widget/ExpandableListView;Landroid/view/View;IJ)Z

方法参数列表对应的方法签名如下:

字节码 invokespecial, invokevirtual, invokeinterface, invokestatic, invokedynamic 有何区别?

invokespecial,一般指的是调用 super 方法,构造方法,private 方法等;

调用的都是一些确定调用者的方法。调用一个类的方法,调用者还能有不确定的时候?
有呀,比如重载,是不是能将父类的方法调用转而变成子类的?
类中非 private 成员方法,一般调用指令为 invokevirtual
invokeinterface, invokestatic 字面意思理解就可以了

思考:抽象类抽象方法调用和接口方法调用指令一样吗?加了final修饰的方法不能被复写,指令会有变化吗?


ASM 可以直接生成 .class文件,也可以在该类被 java 虚拟机加载之前,动态改变现有类的行为。

ASM 涉及了五个比较核心的类:

主要用来重新构建编译后的类,比如修改类名,属性以及方法,甚至可以生产新的类名字节码。

主要是控制方法访问,它有几个重要的方法: onMethodEnter(), visitEnd()visitAnnotation()onMethodEnter() 主要是进入方法时会调用,visitEnd() 主要是扫描器完成类扫描时才会调用,visitAnnotation() 可以在这里通过注解的方式操作字节码。

负责 "拜访" 类成员信息 其中包括类的注解,类的构造方法,类的字段,类的方法,静态代码块,重点需要了解的有: visit()visitMehtod()

ASM 原理

ASM 的官网

ASM4 使用手册(中文版)

Download 010 Editor

上一篇 下一篇

猜你喜欢

热点阅读