ASM之ClassWriter
ClassWriter的父类是ClassVistor,它可以在编辑完字节码后通过toByteArray()方法将所有的visit做的操作转换为byte[],而这些byte[]的内容就遵循classFile的结构,所以将其通过FileOutputStream
写入文件后就是可执行的class文件
先说ClassWriter的结构
这是classWriter定义的字段
public class ClassWriter extends ClassVisitor {
private int version;
private final SymbolTable symbolTable;
private int accessFlags;
private int thisClass;
private int superClass;
private int interfaceCount;
private int[] interfaces;
private FieldWriter firstField;
private FieldWriter lastField;
private MethodWriter firstMethod;
private MethodWriter lastMethod;
private Attribute firstAttribute;
//......
}
可以发现上面的字段和classFile的结构一样
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
然后我们看看ClassWriter的构造方法
这里推荐使用flags使用COMPUTE_FRAMES
,这个flags作用如下图,主要作用在classFile结构的方法表里面
在创建ClassWriter对象时,我们可以传入的flags可选值有三个
- 0:ASM不会自动计算max stacks、max locals、stack map frames
- COMPUTE_MAXS:ASM会自动计算max stacks、max locals,但不会计算stack map frames,这样开发效率是比较高的
- COMPUTE_FRAMES:ASM会自动计算max stacks、max locals、stack map frames,这样开发效率比较低下,但是不需要我们手动计算出以上的这些值
public class ClassWriter extends ClassVisitor {
/* A flag to automatically compute the maximum stack size and the maximum number of local variables of methods. */
public static final int COMPUTE_MAXS = 1;
/* A flag to automatically compute the stack map frames of methods from scratch. */
public static final int COMPUTE_FRAMES = 2;
// flags option can be used to modify the default behavior of this class.
// Must be zero or more of COMPUTE_MAXS and COMPUTE_FRAMES.
public ClassWriter(final int flags) {
this(null, flags);
}
}
中间会被调用的visit方法请查看
最后我们需要生成class的字节码时会调用toByteArray()方法,这个方法通过三个步骤最终获得byte[]
- 计算size大小
- 将数据填充到byte[]
- 将byte[]返回