[toc]
https://asm.ow2.io/javadoc/
有點亂, 當記憶用。
## Class
在 `ASM` 的核心 `API` 中,基于 `ClassVisitor` 的三个组件:
- `ClassReader` 用于解析分析分析类文件,转成 `ASM` 框架能分析的格式。然后在 `accept` 方法中接收一个 `ClassVisitor` 对象用于访问该类;
- `ClassWriter` 是 `ClassVisitor` 的子类,直接通过二进制的形式生成类;
- `ClassVisitor` 类可以看作一个事件筛选器,完成对类的访问遍历。
### ClassWriter
`new ClassWriter(int)` Constructs a new ClassWriter object.
`new ClassWriter(ClassReader, int)` Constructs a new ClassWriter object and enables optimizations for "mostly add" bytecode transformations.
int 有
- `COMPUTE_FRAMES` A flag to automatically compute the stack map frames of methods from scratch.
- `COMPUTE_MAXS`
A flag to automatically compute the maximum stack size and the maximum number of local variables of methods.
### ClassVisitor
`void
accept(ClassVisitor classVisitor, int parsingOptions)`
Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this ClassReader.
classVisitor – the visitor that must visit this class. flags – option flags that can be used to modify the default behavior of this class. See SKIP_DEBUG, EXPAND_FRAMES , SKIP_FRAMES, SKIP_CODE.
### ClassVisitor
用于访问 `Java` 类文件。
在访问一个类文件时,它的回调方法必须按照以下顺序访问:`visit` 【 `visitSource` 】【 `visitModule` 】【 `visitNestHost` 】【 `visitPermittedclass` 】【 `visitOuterClass` 】 ( `visitAnnotation` | `visitTypeAnnotation` | `visitAttribute` )* ( `visitNestMember` | `visitInnerClass` | `visitRecordComponent` | `visitField` | `visitMethod` )* `visitEnd`。
方法说明:
- `visit` :访问类的头部,其中 `version` 指类创建时使用的 `JDK` 的版本,比如 `50` 代表 `JDK1.6`、`51` 代表 `JDK1.7`。`access` 代表类的访问权限,比如 `public `、`private`。`name` 表示类名。`signature` 表示类的签名,如果类不是泛型或者没有继承泛型类,那么`signature` 值为空。`superName` 表示父类的名称。`interfaces` 表示实现的接口;
- `visitSource` :访问类源文件;
- `visitModule`:访问 `Module` 模块, `Java9` 中新增关键字 `module` 用于定义代码和数据的封装体;
- `visitNestHost`:访问嵌套类;
- `visitOuterClass`:访问外部类;
- `visitAnnotation`:访问类的注解;
- `visitTypeAnnotation`:访问类的泛型签名的注解;
- `visitField`:访问类的 `Field` 字段;
* `visitMethod`:访问类的方法;
`public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] ex)`
访问标志,方法名,方法描述符,泛型签名和抛出异常列表
- `visitEnd`:结束。
## Method
### Type Descriptors
- byte B
- char C
- double D
- float F
- int I
- long J
- short S
- boolean Z
- void V
- Object type `L<classname>`; Example: `Ljava/lang/String`;
- Array type `[Type` Example: `[I` (int array), `[Ljava/lang/String;` (String array)
### Method Descriptor
`(<parameter-descriptors>)<return-descriptor>`
`void myMethod()` `()V`
`void myMethod(int x)` `( I )V`
`String myMethod(int a, double b, boolean c)` `( I D Z ) Ljava/lang/String;`
`int[] myMethod(String s)` `( Ljava/lang/String; )[I`
`void myMethod(int[] arr)` `( [I )V`
### MethodVisitor
在访问方法时,会按照以下顺序进行处理:`( visitParameter )* 【 visitAnnotationDefault 】 ( visitAnnotation | visitAnnotableParameterCount | visitParameterAnnotation visitTypeAnnotation | visitAttribute )* 【 visitCode ( visitFrame | visit<i>X</i>Insn | visitLabel | visitInsnAnnotation | visitTryCatchBlock | visitTryCatchAnnotation | visitLocalVariable | visitLocalVariableAnnotation | visitLineNumber )* visitMaxs 】 visitEnd`。
方法说明:
- `visitCode`:开始访问方法;
- `visitParameter(String name, int access)`:访问方法参数;
- `visitAnnotation`:访问方法的注解;
- `visitParameterAnnotation`:访问方法参数的注解;
- `visitFrame`:访问当前栈帧,即当前的局部变量表和操作数栈的状态;
- `visitFieldInsn`:访问一个字段时的指令,即加载一个字段(`load`)或保存一个字段值(`store`);
- `visitIincInsn`:访问一个 `IINC` 指令;
- `visitIntInsn(int opcode, int operand)`:访问一个 `int` 数值类型指令,当 `int` 取值 `-1~5` 采用 `ICONST` 指令,取值 `-128~127` 采用 `BIPUSH` 指令,取值 `-32768~32767` 采用 `SIPUSH` 指令,取值 `-2147483648~2147483647` 采用 `ldc` 指令;
- `visitInvokeDynamicInsn`:访问一个 `invokedynamic` 指令,一般是 `Lambda` 访问时;
- `visitJumpInsn(int opcode, Label label)`:访问一个 `Jump` 指令;
- `visitLdcInsn(Object value)`:访问一个 `LDC` 常量,并加载到操作数栈;
- `visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface)`:访问方法时的指令,即调用方法的指令,比如在一个方法中调用另一个方法;
- `visitVarInsn(int opcode, int var)`:访问局部变量指令,局部变量指令是加载或存储局部变量值的指令,opcode 取值为 GETSTATIC, PUTSTATIC, GETFIELD 或 PUTFIELD,即访问的字段只能是实例字段或静态字段,对于 static final 类型的无法访问;
- `visitLineNumber(int line, Label start)`:访问方法行号声明;
- `visitTryCatchBlock`:访问 `try..catch` 块;
- `visitInsn(int opcode)`:访问一个字节码指令,比如 `IADD`、`ISUB`、`F2L`、`LSHR` 等;
- `visitMax(int maxStack, int maxLocals)`:方法的局部变量表和操作数栈的最大个数;
- `visitEnd`:方法访问结束,结束时必须调用。
## JVM Operands
- `ALOAD <index>`
load a reference onto the stack from a local variable #index
- `ILOAD <index>`
load an int value from a local variable #index
- `ICONST_0`
load the int value 0 onto the stack
- `POP`
discard the top value on the stack
- `RETURN`
return void from method
- `GETFIELD <className> <fieldName> <descriptor>`
get a field value of an object objectref, where the field is identified by field reference in the constant pool index (indexbyte1 << 8 | indexbyte2)
- `NEW <className>`
create new object of type identified by class reference in constant pool index (indexbyte1 << 8 | indexbyte2)
- `DUP`
duplicate the value on top of the stack
- `INVOKESPECIAL <className> <fieldName> <descriptor>`
invoke instance method on object objectref and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 | indexbyte2)
- `INVOKEINTERFACE <className> <fieldName> <descriptor> <isinterface>`
invokes an interface method on object objectref and puts the result on the stack (might be void); the interface method is identified by method reference index in constant pool (indexbyte1 << 8 | indexbyte2)
- `INVOKESTATIC`
invoke a static method and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 | indexbyte2)
- `IFNE`
if value is not 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 | branchbyte2)
- `IFEQ`
if value is 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 | branchbyte2)