类
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);
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
1 2 3
| ClassWriter cw = new ClassWriter(0); TraceClassVisitor tcv = new TraceClassVisitor(cw, printWriter); CheckClassA
|