AMS4使用指南
实战java虚拟机
泛型
类使用泛型
在类定义当中使用范型时,需要增加Signature字段来添加范型信息。该Signature的组成是“<范型参数名:范型扩展的类:范型扩展的接口…>父类描述接口描述”
cw.visit(V1_7, ACC_PUBLIC, clazzPath, "<T:Ljava/lang/String;G:Ljava/lang/Date;>Ljava/lang/Thread;Ljava/lang/AutoCloseable;", "java/lang/Thread", new String[] { "java/lang/AutoCloseable"});
结果
package cn.asm;
public class Generic<T extends String, G extends Date> extends Thread implements AutoCloseable {
}
字段使用泛型
cw.visitField(ACC_PRIVATE, "cache","Ljava/util/Map;", "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;", null).visitEnd();
结果
private Map<String, Object> cache;
方法使用泛型
cw.visitMethod(ACC_PUBLIC, "getList","(Ljava/util/Map;)Ljava/util/List;","(Ljava/util/Map<Ljava/lang/String;Ljava/lang/Integer;>;)Ljava/util/List<Ljava/lang/String;>;",null).visitEnd();
结果
public List<String> getList(Map<String, Integer> var1) {
}
SignatureVisitor
public abstract class SignatureVisitor {
public final static char EXTENDS = ’+’;
public final static char SUPER = ’-’;
public final static char INSTANCEOF = ’=’;
public SignatureVisitor(int api);
public void visitFormalTypeParameter(String name);
public SignatureVisitor visitClassBound();
public SignatureVisitor visitInterfaceBound();
public SignatureVisitor visitSuperclass();
public SignatureVisitor visitInterface();
public SignatureVisitor visitParameterType();
public SignatureVisitor visitReturnType();
public SignatureVisitor visitExceptionType();
public void visitBaseType(char descriptor);
public void visitTypeVariable(String name);
public SignatureVisitor visitArrayType();
public void visitClassType(String name);
public void visitInnerClassType(String name);
public void visitTypeArgument();
public SignatureVisitor visitTypeArgument(char wildcard);
public void visitEnd();
}
注解
类、字段、方法和方法参数注释,比如@Deprecated 或@Override,
只要它们的保留策略不是 RetentionPolicy.SOURCE,它们就会被存储在编译后的类中,这一信息不是在运行时供字节代码指令使用。
但是,如果保留策略是 RetentionPolicy.RUNTIME,则可以通过反射 API 访问它。它还可以供编译器使用。
定义注解
定义注解acc必须包含ACC_ANNOTATION|ACC_INTERFACE,以及必须继承java/lang/annotation/Annotation接口。
ClassWriter cw = new ClassWriter(0);
//定义注解信息:
cw.visit(V1_7, ACC_PUBLIC|ACC_ANNOTATION|ACC_INTERFACE, clazzPath, null, "java/lang/Object", new String[]{ "java/lang/annotation/Annotation" });
//注解属性 cacheable
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "cacheable","()Z", null, null);
AnnotationVisitor av = mv.visitAnnotationDefault();
av.visit(null,false);
mv.visitEnd();
//注解属性 key
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "key","()Ljava/lang/String;", null, null);
mv.visitEnd();
运行结果:
public @interface Anno {
boolean cacheable() default false;
String key();
}
使用注解
注意:不校验注解类是否存在,也不校验属性是否存在,也不校验类型是否匹配
//类上是用注解。
AnnotationVisitor av = cw.visitAnnotation("cn/Anno",false);
av.visit("cacheable",1);//与定义的值类型不匹配
av.visit("noexistkey","aa"); //不存在的key
av.visitEnd();
//方法上是用注解
MethodVisitor.visitAnnotation("cn/Anno",false);
//字段上是用注解
FieldVisitor.visitAnnotation("cn/Anno",false);
AnnotationVisitor
public abstract class AnnotationVisitor {
public AnnotationVisitor(int api);
public AnnotationVisitor(int api, AnnotationVisitor av);
public void visit(String name, Object value);
public void visitEnum(String name, String desc, String value);
public AnnotationVisitor visitAnnotation(String name, String desc);
public AnnotationVisitor visitArray(String name);
public void visitEnd();
}
工具
- TraceAnnotationVisitor
- CheckAnnotationAdapter