---
# System prepended metadata

title: Bytecode and OW2 ASM
tags: [Java]

---

[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)