下面列出了org.objectweb.asm.AnnotationVisitor#visitEnd ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private static void writeField(ClassWriter classWriter, FieldNode field) {
FieldVisitor fieldVisitor;
if (field.isJoinNode()) {
if (EntityRelationship.ManyToOne.equals(field.getEntityRelationship())) {
fieldVisitor = classWriter.visitField(ACC_PRIVATE, field.getName(), field.getTypeDesc(), null, null);
} else { // OneToMany or ManyToMany
fieldVisitor = classWriter.visitField(ACC_PRIVATE, field.getName(), "Ljava/util/Set;", getTypeSiganitureForOneToMany(field.getTypeDesc()), null);
}
// ignore join field for json
AnnotationVisitor annotationVisitor0 = fieldVisitor.visitAnnotation("Lcom/fasterxml/jackson/annotation/JsonIgnore;", true);
annotationVisitor0.visitEnd();
} else {
fieldVisitor = classWriter.visitField(ACC_PRIVATE, field.getName(), typeMap.get(field.getType()), null, null);
}
fieldVisitor.visitEnd();
}
/**
* Adds a public marker method that returns true.
*
* <p>It appears like so: <pre>
* public boolean name() {
* return true;
* }
* </pre></p>
*
* @param name The name of the generated method
*/
private void visitMarkerMethod(String name) {
MethodVisitor isCancelable = super.visitMethod(Opcodes.ACC_PUBLIC, name, BOOLEAN_DESCRIPTOR, null, null);
if (isCancelable != null) {
AnnotationVisitor override = isCancelable.visitAnnotation("Ljava/lang/Override;", true);
if (override != null) {
override.visitEnd();
}
isCancelable.visitInsn(Opcodes.ICONST_1);
isCancelable.visitInsn(Opcodes.IRETURN);
isCancelable.visitMaxs(2, 1);
isCancelable.visitEnd();
}
}
public static void acceptAnnotation(final AnnotationVisitor av, final String name,
final Object value) {
if (value instanceof String[]) {
String[] typeconst = (String[]) value;
av.visitEnum(name, typeconst[0], typeconst[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode an = (AnnotationNode) value;
an.accept(av.visitAnnotation(name, an.desc));
} else if (value instanceof List<?>) {
AnnotationVisitor v = av.visitArray(name);
List<?> array = (List<?>) value;
for (int j = 0; j < array.size(); ++j) {
acceptAnnotation(v, null, array.get(j));
}
v.visitEnd();
} else {
av.visit(name, value);
}
}
/**
* Makes the given visitor visit a given annotation value.
*
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
* @param name the value name.
* @param value the actual value.
*/
static void accept(
final AnnotationVisitor annotationVisitor, final String name, final Object value) {
if (annotationVisitor != null) {
if (value instanceof String[]) {
String[] typeValue = (String[]) value;
annotationVisitor.visitEnum(name, typeValue[0], typeValue[1]);
} else if (value instanceof AnnotationNode) {
AnnotationNode annotationValue = (AnnotationNode) value;
annotationValue.accept(annotationVisitor.visitAnnotation(name, annotationValue.desc));
} else if (value instanceof List) {
AnnotationVisitor arrayAnnotationVisitor = annotationVisitor.visitArray(name);
if (arrayAnnotationVisitor != null) {
List<?> arrayValue = (List<?>) value;
for (int i = 0, n = arrayValue.size(); i < n; ++i) {
accept(arrayAnnotationVisitor, null, arrayValue.get(i));
}
arrayAnnotationVisitor.visitEnd();
}
} else {
annotationVisitor.visit(name, value);
}
}
}
@Override
public void visitSource(String source, String debug) {
super.visitSource(source, debug);
AnnotationVisitor av = this.cv.visitAnnotation("Lorg/spongepowered/asm/mixin/transformer/meta/MixinInner;", false);
av.visit("mixin", this.info.getOwner().toString());
av.visit("name", this.info.getOriginalName().substring(this.info.getOriginalName().lastIndexOf('/') + 1));
av.visitEnd();
}
/**
* Makes the given visitor visit this annotation.
*
* @param annotationVisitor an annotation visitor. Maybe {@literal null}.
*/
public void accept(final AnnotationVisitor annotationVisitor) {
if (annotationVisitor != null) {
if (values != null) {
for (int i = 0, n = values.size(); i < n; i += 2) {
String name = (String) values.get(i);
Object value = values.get(i + 1);
accept(annotationVisitor, name, value);
}
}
annotationVisitor.visitEnd();
}
}
@Override
public void end(final String name) {
AnnotationVisitor av = (AnnotationVisitor) pop();
if (av != null) {
av.visitEnd();
}
}
static void visitAnnotationValue(AnnotationVisitor visitor, String key, Object value) {
if (value.getClass().isArray()) {
AnnotationVisitor arrayVisitor = visitor.visitArray(key);
for (Object arrayValue : (Object[]) value) {
// Default key is 'value'. It can be changed by using AnnotationValue type.
visitAnnotationValue(arrayVisitor, "value", arrayValue);
}
arrayVisitor.visitEnd();
} else if (value instanceof AnnotationValue) {
AnnotationValue annotationValue = (AnnotationValue) value;
visitor.visit(annotationValue.name(), annotationValue.value());
} else {
visitor.visit(key, value);
}
}
@Test
public void annotationDeclaration() {
ClassWriter cw = new ClassWriter(0);
cw.visit(
52,
Opcodes.ACC_PUBLIC + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ABSTRACT + Opcodes.ACC_INTERFACE,
"test/Hello",
null,
"java/lang/Object",
new String[] {"java/lang/annotation/Annotation"});
AnnotationVisitor av = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
av.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
av.visitEnd();
cw.visitEnd();
byte[] bytes = cw.toByteArray();
ClassFile classFile = com.google.turbine.bytecode.ClassReader.read(null, bytes);
assertThat(classFile.access())
.isEqualTo(
TurbineFlag.ACC_PUBLIC
| TurbineFlag.ACC_ANNOTATION
| TurbineFlag.ACC_ABSTRACT
| TurbineFlag.ACC_INTERFACE);
assertThat(classFile.name()).isEqualTo("test/Hello");
assertThat(classFile.signature()).isNull();
assertThat(classFile.superName()).isEqualTo("java/lang/Object");
assertThat(classFile.interfaces()).containsExactly("java/lang/annotation/Annotation");
assertThat(classFile.annotations()).hasSize(1);
ClassFile.AnnotationInfo annotation = Iterables.getOnlyElement(classFile.annotations());
assertThat(annotation.typeName()).isEqualTo("Ljava/lang/annotation/Retention;");
assertThat(annotation.elementValuePairs()).hasSize(1);
assertThat(annotation.elementValuePairs()).containsKey("value");
ElementValue value = annotation.elementValuePairs().get("value");
assertThat(value.kind()).isEqualTo(ElementValue.Kind.ENUM);
ElementValue.EnumConstValue enumValue = (ElementValue.EnumConstValue) value;
assertThat(enumValue.typeName()).isEqualTo("Ljava/lang/annotation/RetentionPolicy;");
assertThat(enumValue.constName()).isEqualTo("RUNTIME");
}
private void visitDefaultValue(ExecutableElement e, MethodVisitor methodVisitor) {
AnnotationValue defaultValue = e.getDefaultValue();
if (defaultValue == null) {
return;
}
AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault();
visitAnnotationValue(null, defaultValue, annotationVisitor);
annotationVisitor.visitEnd();
}
public static void addNullablefieldAnnotation(AnnotationVisitor av0, boolean[] nullstatus) {
AnnotationVisitor av1 = av0.visitArray("nullable");
for(boolean item : nullstatus) {
av1.visit(null, item?Boolean.TRUE:Boolean.FALSE);
}
av1.visitEnd();
}
@Override
public void visitEnd() {
super.visitEnd();
for (AnnotationVisitor dest : moreDestinations) {
dest.visitEnd();
}
}
@Override
public void end(final String name) {
AnnotationVisitor av = (AnnotationVisitor) pop();
if (av != null) {
av.visitEnd();
}
}
@Override
public void visitEnd() {
if (!skipEnchancing) {
AnnotationVisitor v = super.visitAnnotation(MaybeContinuableClassVisitor.SKIP_ENCHANCING_ANNOTATION, true);
if (null != v) {
v.visitEnd();
}
}
super.visitEnd();
}
private void visitParameterAnnotations(final Parameter parameter, final int paramNumber, final MethodVisitor mv) {
for (AnnotationNode an : parameter.getAnnotations()) {
// skip built-in properties
if (an.isBuiltIn()) continue;
if (an.hasSourceRetention()) continue;
final String annotationDescriptor = BytecodeHelper.getTypeDescription(an.getClassNode());
AnnotationVisitor av = mv.visitParameterAnnotation(paramNumber, annotationDescriptor, an.hasRuntimeRetention());
visitAnnotationAttributes(an, av);
av.visitEnd();
}
}
@Override
protected void generate(TraceClassVisitor cw) {
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "soot/asm/backend/targets/AnnotatedMethod",
null, "java/lang/Object", null);
cw.visitSource("AnnotatedMethod.java", null);
{
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC, "doSth", "()V", null, null);
{
av0 = mv.visitAnnotation("Lsoot/asm/backend/targets/MyTestAnnotation;", true);
av0.visit("iVal", new Integer(124));
av0.visit("fVal", new Float("5132.0"));
av0.visit("lVal", new Long(5123L));
av0.visit("dVal", new Double("745.0"));
av0.visit("zVal", Boolean.TRUE);
av0.visit("bVal", new Byte((byte)1));
av0.visit("sVal", new Short((short)123));
av0.visit("strVal", "435243");
av0.visit("rVal", Type.getType("Lsoot/asm/backend/targets/AnnotatedClass;"));
av0.visit("iAVal", new int[] {123,234,345,456});
{
AnnotationVisitor av1 = av0.visitArray("sAVal");
av1.visit(null, "A");
av1.visit(null, "B");
av1.visit(null, "C");
av1.visitEnd();
}
av0.visitEnd();
}
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
cw.visitEnd();
}
@Override
protected void generate(TraceClassVisitor cw) {
MethodVisitor mv;
AnnotationVisitor av0;
cw.visit(V1_5, ACC_PUBLIC + ACC_ANNOTATION + ACC_ABSTRACT
+ ACC_INTERFACE, "soot/asm/backend/targets/MyTestAnnotation", null,
"java/lang/Object",
new String[] { "java/lang/annotation/Annotation" });
cw.visitSource("MyTestAnnotation.java", null);
{
av0 = cw.visitAnnotation("Ljava/lang/annotation/Retention;", true);
av0.visitEnum("value", "Ljava/lang/annotation/RetentionPolicy;", "RUNTIME");
av0.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "bVal", "()B", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "dVal", "()D", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "fVal", "()F", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "iAVal", "()[I", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "iVal", "()I", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "lVal", "()J", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "rVal", "()Ljava/lang/Class;",
"()Ljava/lang/Class<Lsoot/asm/backend/targets/AnnotatedClass;>;", null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "sAVal", "()[Ljava/lang/String;", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "sVal", "()S", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "strVal", "()Ljava/lang/String;", null, null);
mv.visitEnd();
}
{
mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "zVal", "()Z", null, null);
mv.visitEnd();
}
cw.visitEnd();
}
/**
* Write the class bytes to the given class output.
*
* @param classOutput the class output (must not be {@code null})
*/
public void writeTo(ClassOutput classOutput) {
Objects.requireNonNull(classOutput);
ClassWriter file = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
final GizmoClassVisitor cv = new GizmoClassVisitor(Gizmo.ASM_API_VERSION, file, classOutput.getSourceWriter(className));
String[] interfaces = this.interfaces.clone();
cv.visit(Opcodes.V1_8, ACC_PUBLIC | ACC_SUPER | ACC_SYNTHETIC | extraAccess, className, signature, superClass, interfaces);
cv.visitSource(null, null);
boolean requiresCtor = true;
for (MethodDescriptor m : methods.keySet()) {
if (m.getName().equals("<init>")) {
requiresCtor = false;
break;
}
}
if (requiresCtor) {
// constructor
cv.append("// Auto-generated constructor").newLine();
GizmoMethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
mv.visitVarInsn(ALOAD, 0); // push `this` to the operand stack
mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "()V", false); // call the constructor of super class
mv.visitInsn(RETURN);
mv.visitMaxs(0, 1);
mv.visitEnd();
}
//now add the fields
for (Map.Entry<FieldDescriptor, FieldCreatorImpl> field : fields.entrySet()) {
field.getValue().write(cv);
}
for (Map.Entry<MethodDescriptor, MethodCreatorImpl> method : methods.entrySet()) {
method.getValue().write(cv);
}
for(AnnotationCreatorImpl annotation : annotations) {
AnnotationVisitor av = cv.visitAnnotation(DescriptorUtils.extToInt(annotation.getAnnotationType()), annotation.getRetentionPolicy() == RetentionPolicy.RUNTIME);
for(Map.Entry<String, Object> e : annotation.getValues().entrySet()) {
AnnotationUtils.visitAnnotationValue(av, e.getKey(), e.getValue());
}
av.visitEnd();
}
cv.visitEnd();
classOutput.write(className, file.toByteArray());
}
private static void visitAnnotation(MethodVisitor mv, String descriptor) {
AnnotationVisitor av = mv.visitAnnotation(descriptor, true);
checkNotNull(av);
av.visitEnd();
}
public void accept(AnnotationVisitor visitor)
{
for (Element element : elements)
visitor.visit(element.getName(), element.getValue());
visitor.visitEnd();
}