0%

ASM4-结构

2.1 类的结构

2.1.1 已编译类的整体结构

内容 子内容
修饰符、名字、超类、接口
常量池:数值、字符串、类型常量
源文件名(可选)
封装的类引用
注释*
属性*
内部类* 名称
字段* 修饰符、名字、类型
注释
属性
方法* 修饰符、名字、返回类型、参数类型
注释
属性
编译后的代码

* 表示0个到多个

2.1.2 类型描述符

Java类型 类型表述符
boolean Z
char C
byte B
short S
int I
float F
long J
Double D
Object Ljava/lang/Object;
int[] [I
Object[][] [[Ljava/lang/Object;

2.1.3 类型描述符

源文件中的方法声明 方法描述符
Void main (int i, float f) (IF)V
int m(Object o) (Ljava.lang.Object;)I
int[] m (int i, String s) (ILjava/lang/String;)I[
Object m(int[] i) ([I)Ljava/lang/Object;

2.2 接口和组件

2.2.1 介绍

ClassVistor 就是就是个模板 我们对类的处理都通过这个模板生成的类来进行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public abstract class ClassVisitor {
public ClassVistor(int api);
public ClassVistor(int api, ClassVistor cv);
/**
* verison 版本信息
* access 权限信息
* name 类的名称
* signature 泛化
* superName 父类信息
* interface 接口信息
*/
public void visit(int version, int access, String name, String signature, String superName, String[] interface);

public void visitSource(String source, String debug);

public void visitOuterClass(String ower, String name, String desc);

AnnotationVisitor visitAnnotation(String desc, Boolean visible);

public void visitAttribute(Attribute attr);

public void visitInnerClass(String name, String outerName, String innerName, int access);

public FieldVisitor visitField(int access, String name, String desc, String signature, Object value);

public MethodVisitor visitorMethod(int access, String name, String desc, String signature, String[] exceptions);

void visitEnd();
}

在上面的类中返回了 AnnotationVisitor, FieldVisitor, MethodVisitor.

1
2
3
4
5
6
7
public abstract class FieldVisitor {
public FieldVisitor(int api);
public FieldVisitor(int api, FieldVisitor fv);
public AnnotationVisitor visitorAnnotation(String desc, boolean visible);
public void visitAttribute(Attribute attr);
public void visitEnd();
}

ClassVisitor 类的方法必须按照以下的顺序进行调用

visit visitSourcce? visitOuterClass? (visitAnnotation | visitAttribute)* (visitInnerClass | visitField | visitMethod) * visitEnd

ASM提供了三个基于ClassVisitor API的核心组件,用于变化和生成类

  • ClassReader *分析以字节数组形式给出的已编译类,并针对其accept方法参数中传送的ClassVisitor实例, 调用相应的visit方法。这个类可以看作是一个时间生成器。
  • ClassWriter 是ClassVisitor抽象类的一个子类,它直接以二进行形式生成编译后的类。
  • ClassVisitor 类将它收到的所有方法调用都委托为另一个ClassVistor类。可以看作是事件筛选器。

2.2.2 分析类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
ClassReader classReader = new ClassReader("java.lang.Runnable");
classReader.accept(new ClassVisitor(ASM4) {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interface) {
System.out.println(name + "extends" + superName + "{ ");
}
@Override
public void visitSource(String source, String debug) {

}
@Override
public void visitOuterClass(String ower, String name, String desc) {

}
@Override
AnnotationVisitor visitAnnotation(String desc, Boolean visible) {
return null;
}
@Override
public void visitAttribute(Attribute attr) {

}
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {

}
@Override
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
System.out.println(" " + desc + " " + name);
return null;
}
@Override
public MethodVisitor visitorMethod(int access, String name, String desc, String signature, String[] exceptions) {
System.out.println(" " + name + desc);
}

void visitEnd() {
Sysgtem.out.println("}");
}
}, 0);

获得的结果是

java/lang/Runnable extends java/lang/Object {

​ run()V

}

2.2.3 生成类

如果我们想生成类

1
2
3
4
5
6
7
package pkg;
public interface Comparable extends Mesurable {
int LESS = -1;
int EQUAL = 0;
int GRATER = 1;
int compareTo(Object o);
}

我们可以对ClassVisitor进行6次方法调用来生成它:

1
2
3
4
5
6
7
8
9
10
11
ClassWriter cw = new ClassWriter();
cw.visitor(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, "pkg/Comparable", null, "java/lang/Object");
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "LESS", "I", null, new Integer(-1)).visitEnd();
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "EQUAL", "I", null, new Integer(0)).visitEnd();
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "GRATER", "I", null, new Integer(1)).visitEnd();

cw.visitField(ACC_PUBLIC + ACC_ABSTRACT, "compareTo", "(Ljava/lang/Object;)I", null, null).visitEnd();

cw.visitEnd();

byte[] b = cw.toByteArray();

产生的中间码可以被clasLoader

new ClassLoad().defineClass(“pkg.Comparable”, b, 0, b.length);

或者

1
2
3
4
5
6
7
8
9
10
11
12
class StubClassLoader extend ClassLoader {
@Override
protected Class findClass(BeanDenefication bd) {
if (bd.isProxyed) {
ClassWriter cw = new ClassWriter();
byte[] b = cw.getByteArray();
return defineClass(name, b, 0, b.length);
} else {
bd.getClass();
}
}
}

这个可能是Spring 生成类的方式

2.2.4转换类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class ChangeVersionAdapter extends ClassVisitor {
public ChangeVisionAdapter(ClassVisitor cv) {
super (ASM4, cv);
}

@Override
public void visit(int version, int access, String name,
String signature, String superName, String[] interfaces) {
cv.visit(V1_6, access, name, signature, superName, interfaces);
}
}

try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("path")) {
int size = inputStream.available();
byte[] bytes = new byte[size];
inputStream.read(bytes);
ClassReader classReader = new ClassReader(bytes);
ClassWriter classWriter = new ClassWriter(classReader , 0);
ClassVisitor classVisitor = new ChangeVersionAdapter(classWriter);
classReader.accept(classVisitor, 0);
} catch (Exception e) {
e.printStackTrace();
}

2.2.5 移除类成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class RemoveMethodAdapter extends ClassVisitor {
private String mName;
private String mDesc;
public RemoveMethodAdapter(ClassVisitor cv, String mName, String mDesc) {
super(ASM4, cv);
this.mName = mName;
this.mDesc = mDesc;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals(mName) && desc.equals(mDesc)) {
return null;
}
return cv.visitMethod(access, name, desc, signature, exceptions);
}
}

2.2.6 增加类成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class AddFieldAdapter extends ClassVisitor {
private int fAcc;
private String fName;
private String fDesc;
private boolean isFieldPresent;

public AddFieldAdapter(ClassVisitor cv, int fAcc, String fName, String fDesc) {
super(ASM4, cv);
this.fAcc = fAcc;
this.fName = fName;
this.fDesc = fDesc;
}

public FieldVisitor fieldVisitor(int access, String name, String desc, String signature, Object value) {
if (name.equals(fName)) {
isFieldPresent = true;
}
return cv.visitField(access, name, desc, signature, value);
}

@Override
public void visitEnd() {
if (! isFieldPresent) {
FieldVisitor fv = cv.visitField(fAcc, fName, fDesc, null, null);
if ( fv != null) {
fv.visitEnd();
}
}
cv.visitEnd();
}
}

我们只是检测一下我们我们要添加的字段是不是存在的, 如果不存在的话,我们进行字段的添加

2.2.7 转化链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MultiClassAdapter extends ClassVisitor {
protected ClassVisitor[] cvs;

public MultiClassAdapter(ClassVisitor[] cvs) {
super(ASM4);
this.cvs = cvs;
}

@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
for (ClassVisitor cv : cvs) {
cv.visit(version, access, name, signature, superName, interfaces);
}
}
}

2.2.8 TraceClassVisitor & CheckClassAdapter

  • TraceClassVisitor

    以获得关于实际所生成内容的一个可读轨迹

  • CheckClassAdapter

    验证其对方法的调用顺序是否恰当,参数是否有效,然后才会委托给一下个防蚊器。当发生错误时,会抛出IllegaStateException或IllegalArgumentException

1
2
3
ClassWriter cw = new ClassWriter(0);
TraceClassVisitor tcv = new TraceClassVisitor(cw, printWriter);
CheckClassA