List of usage examples for org.objectweb.asm.tree ClassNode ClassNode
public ClassNode()
From source file:org.wisdom.ipojo.module.WisdomViewVisitorTest.java
License:Apache License
@Test public void parseEmptyAnnotation() { Reporter reporter = new SystemReporter(); ComponentWorkbench workbench = mock(ComponentWorkbench.class); when(workbench.getType()).thenReturn(Type.getType(MyComponent.class)); when(workbench.getClassNode()).thenReturn(new ClassNode()); when(workbench.getElements()).thenReturn(elements); FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "template", Type.getDescriptor(Template.class), null, null);/* w w w. j a v a 2 s.c o m*/ WisdomViewVisitor visitor = new WisdomViewVisitor(workbench, reporter, node); visitor.visitEnd(); assertThat(elements).hasSize(0); }
From source file:org.wisdom.ipojo.module.WisdomViewVisitorTest.java
License:Apache License
@Test public void parseViewOnNotTemplateField() { Reporter reporter = new SystemReporter(); ComponentWorkbench workbench = mock(ComponentWorkbench.class); when(workbench.getType()).thenReturn(Type.getType(MyComponent.class)); when(workbench.getClassNode()).thenReturn(new ClassNode()); when(workbench.getElements()).thenReturn(elements); FieldNode node = new FieldNode(Opcodes.ACC_PROTECTED, "template", Type.getDescriptor(String.class), null, null);//from w w w.j av a 2 s . c om WisdomViewVisitor visitor = new WisdomViewVisitor(workbench, reporter, node); visitor.visit("value", "index"); visitor.visitEnd(); assertThat(elements).hasSize(1); Element element = elements.keySet().iterator().next(); assertThat(element.getName()).isEqualTo("requires"); assertThat(element.getAttribute("field")).isEqualTo("template"); assertThat(element.getAttribute("filter")).contains("=index)"); }
From source file:pku.sei.checkedcoverage.tracer.instrumentation.Transformer.java
License:Creative Commons License
private byte[] transform0(final String className, final String javaClassName, final byte[] classfileBuffer) { final ClassReader reader = new ClassReader(classfileBuffer); final ClassNode classNode = new ClassNode(); reader.accept(classNode, 0);//from w w w . jav a 2 s.c om final ClassWriter writer; // we have to synchronize on System.out first. // otherwise it may lead to a deadlock if a thread calls removeStale() on ConcurrentReferenceHashMap // while he holds the lock for System.out, but another thread is inside the transformation step and // waits for the lock of System.out synchronized (System.out) { synchronized (this.transformationLock) { // register that class for later reconstruction of the trace List<Field> fields; if (classNode.fields.isEmpty()) fields = Collections.emptyList(); else fields = new ArrayList<Field>(classNode.fields.size()); final String javaSuperName = Type.getObjectType(classNode.superName).getClassName(); final ReadClass readClass = new ReadClass(className, AbstractInstruction.getNextIndex(), classNode.access, classNode.sourceFile, fields, javaSuperName); for (final Object fieldObj : classNode.fields) { final FieldNode f = (FieldNode) fieldObj; fields.add(new Field(f.name, f.desc, f.access, readClass)); } writer = new FixedClassWriter( COMPUTE_FRAMES ? ClassWriter.COMPUTE_FRAMES : ClassWriter.COMPUTE_MAXS); final ClassVisitor output = this.tracer.check ? new CheckClassAdapter(writer) : writer; if (Arrays.asList(this.pauseTracingClasses).contains(javaClassName) || className.startsWith("java/security/")) { new PauseTracingInstrumenter(readClass, this.tracer).transform(classNode); } else { if ("java/lang/Thread".equals(className)) new ThreadInstrumenter(readClass, this.tracer).transform(classNode); else new TracingClassInstrumenter(readClass, this.tracer).transform(classNode); } new IdentifiableInstrumenter(readClass, this.tracer).transform(classNode); classNode.accept(COMPUTE_FRAMES ? new JSRInliner(output) : output); readClass.setInstructionNumberEnd(AbstractInstruction.getNextIndex()); // now we can write the class out // NOTE: we do not write it out immediately, because this sometimes leads // to circular dependencies! //readClass.writeOut(this.readClassesOutputStream, this.readClassesStringCache); this.readClasses.add(readClass); } } final byte[] newClassfileBuffer = writer.toByteArray(); if (this.tracer.check) { checkClass(newClassfileBuffer, className); } //printClass(newClassfileBuffer, Type.getObjectType(className).getClassName()); /* if (className.endsWith("line/Main")) printClass(newClassfileBuffer, Type.getObjectType(className).getClassName()); */ return newClassfileBuffer; }
From source file:pku.sei.checkedcoverage.tracer.instrumentation.Transformer.java
License:Creative Commons License
private boolean checkClass(final byte[] newClassfileBuffer, final String classname) { final ClassNode cn = new ClassNode(); final ClassReader cr = new ClassReader(newClassfileBuffer); //cr.accept(new CheckClassAdapter(cn), ClassReader.SKIP_DEBUG); cr.accept(new CheckClassAdapter(cn), 0); for (final Object methodObj : cn.methods) { final MethodNode method = (MethodNode) methodObj; final Analyzer a = new Analyzer(new BasicVerifier()); // SimpleVerifier has problems with sub-classes, e.g. you cannot use PrintStream for Appendable and so on... //final Analyzer a = new Analyzer(new SimpleVerifier( // Type.getObjectType(cn.name), Type.getObjectType(cn.superName), // (cn.access & Opcodes.ACC_INTERFACE) != 0)); try {/* ww w. jav a 2s . c o m*/ a.analyze(cn.name, method); } catch (final AnalyzerException e) { System.err.println("Error in method " + classname + "." + method.name + method.desc + ":"); e.printStackTrace(System.err); printMethod(a, System.err, method); return false; } } return true; }
From source file:pl.asie.foamfix.coremod.BlockPosPatch.java
License:Open Source License
public static byte[] patchVec3i(byte[] data) { final ClassReader reader = new ClassReader(data); final ClassNode node = new ClassNode(); reader.accept(node, 8);/*from w w w.jav a 2 s. c o m*/ for (FieldNode fn : node.fields) { if ("I".equals(fn.desc) && fn.access == (Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL)) { fn.access = Opcodes.ACC_PROTECTED; } } final ClassWriter writer = new ClassWriter(8); node.accept(writer); return writer.toByteArray(); }
From source file:pl.asie.foamfix.coremod.FoamFixTransformer.java
License:Open Source License
public byte[] spliceMethods(final byte[] data, final String className, final String targetClassName, final String... methods) { final Set<String> methodSet = Sets.newHashSet(methods); try {//from www . j av a 2 s . c om final byte[] dataSplice = ByteStreams.toByteArray( this.getClass().getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class")); final ClassReader readerData = new ClassReader(data); final ClassReader readerSplice = new ClassReader(dataSplice); final ClassWriter writer = new ClassWriter(8); final String className2 = className.replace('.', '/'); final String targetClassName2 = targetClassName.replace('.', '/'); final Remapper remapper = new Remapper() { public String map(final String name) { return className2.equals(name) ? targetClassName2 : name; } }; ClassNode nodeData = new ClassNode(); ClassNode nodeSplice = new ClassNode(); readerData.accept(nodeData, 8); readerSplice.accept(new RemappingClassAdapter(nodeSplice, remapper), 8); for (int i = 0; i < nodeSplice.methods.size(); i++) { if (methodSet.contains(nodeSplice.methods.get(i).name)) { MethodNode mn = nodeSplice.methods.get(i); boolean added = false; for (int j = 0; j < nodeData.methods.size(); j++) { if (nodeData.methods.get(j).name.equals(mn.name) && nodeData.methods.get(j).desc.equals(mn.desc)) { System.out.println("Spliced in: " + targetClassName + "." + mn.name); nodeData.methods.set(j, mn); added = true; break; } } if (!added) { System.out.println("Added: " + targetClassName + "." + mn.name); nodeData.methods.add(mn); added = true; } } } nodeData.accept(writer); return writer.toByteArray(); } catch (IOException e) { e.printStackTrace(); return null; } }
From source file:pl.clareo.coroutines.core.ClassTransformer.java
License:Apache License
@SuppressWarnings("unchecked") void transform() { for (MethodNode coroutine : coroutines) { if (log.isLoggable(Level.FINEST)) { log.finest("Generating method for coroutine " + coroutine.name + coroutine.desc); }//w w w .java2 s. co m String coroutineName = getCoroutineName(coroutine); MethodTransformer methodTransformer = new MethodTransformer(coroutine, thisType); MethodNode coroutineImpl = methodTransformer.transform(coroutineName, generateDebugCode); thisNode.methods.add(coroutineImpl); /* * generate co iterators and method stubs */ log.finest("Generating CoIterator implementation and method stubs"); String baseCoIteratorName; Map<String, Object> annotation = getCoroutineAnnotationValues(coroutine); if (getBoolean(annotation, "threadLocal")) { baseCoIteratorName = Type.getInternalName(ThreadLocalCoIterator.class); } else { baseCoIteratorName = Type.getInternalName(SingleThreadedCoIterator.class); } String coIteratorClassName = "pl/clareo/coroutines/core/CoIterator" + num; ClassNode coIteratorClass = new ClassNode(); coIteratorClass.version = Opcodes.V1_6; coIteratorClass.access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER; coIteratorClass.name = coIteratorClassName; coIteratorClass.superName = baseCoIteratorName; if (generateDebugCode) { /* * If debugging code is emitted create field keeping JDK logger */ FieldNode loggerField = new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC, "logger", "Ljava/util/logging/Logger;", null, null); coIteratorClass.fields.add(loggerField); MethodNode clinit = new MethodNode(); clinit.access = Opcodes.ACC_STATIC; clinit.name = "<clinit>"; clinit.desc = "()V"; clinit.exceptions = Collections.EMPTY_LIST; String loggerName = thisType.getClassName(); InsnList clinitCode = clinit.instructions; clinitCode.add(new LdcInsnNode(loggerName)); clinitCode.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/logging/Logger", "getLogger", "(Ljava/lang/String;)Ljava/util/logging/Logger;")); clinitCode.add(new FieldInsnNode(Opcodes.PUTSTATIC, coIteratorClassName, "logger", "Ljava/util/logging/Logger;")); clinitCode.add(new InsnNode(Opcodes.RETURN)); clinit.maxStack = 1; clinit.maxLocals = 0; coIteratorClass.methods.add(clinit); } /* * Generate constructor */ MethodNode init = new MethodNode(); init.access = Opcodes.ACC_PUBLIC; init.name = "<init>"; init.desc = CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR; init.exceptions = Collections.EMPTY_LIST; InsnList initCode = init.instructions; initCode.add(new VarInsnNode(Opcodes.ALOAD, 0)); initCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); initCode.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, baseCoIteratorName, "<init>", CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR)); initCode.add(new InsnNode(Opcodes.RETURN)); init.maxStack = 2; init.maxLocals = 2; coIteratorClass.methods.add(init); /* * Generate overriden call to coroutine */ MethodNode call = new MethodNode(); call.access = Opcodes.ACC_PROTECTED; call.name = "call"; call.desc = CALL_METHOD_DESCRIPTOR; call.exceptions = Collections.EMPTY_LIST; InsnList callCode = call.instructions; /* * if debug needed generate call details */ if (generateDebugCode) { String coroutineId = "Coroutine " + coroutine.name; callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER, coroutineId + " call. Caller sent: ", 2)); callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK)); callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINEST, coroutineId + " state ", 1)); callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK)); } /* * push call arguments: this (if not static), frame, input, output */ boolean isStatic = (coroutine.access & Opcodes.ACC_STATIC) != 0; if (!isStatic) { callCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); callCode.add( new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getThis", "()Ljava/lang/Object;")); callCode.add(new TypeInsnNode(Opcodes.CHECKCAST, thisType.getInternalName())); } callCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); callCode.add(new InsnNode(Opcodes.ACONST_NULL)); callCode.add(new VarInsnNode(Opcodes.ALOAD, 2)); callCode.add(new MethodInsnNode(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL, thisType.getInternalName(), coroutineName, COROUTINE_METHOD_DESCRIPTOR)); // stack: * if (!generateDebugCode) { callCode.add(new InsnNode(Opcodes.ARETURN)); } else { // save result display suspension point (two more locals // needed) callCode.add(new VarInsnNode(Opcodes.ASTORE, 3)); callCode.add(new VarInsnNode(Opcodes.ALOAD, 1)); callCode.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLineOfCode", "()I")); callCode.add(box_int(Type.INT)); callCode.add(new VarInsnNode(Opcodes.ASTORE, 4)); callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER, "Coroutine suspended at line ", 4, ". Yielded:", 3)); callCode.add(new FrameNode(Opcodes.F_APPEND, 2, new Object[] { "java/lang/Object", "java/lang/Integer" }, 0, EMPTY_STACK)); callCode.add(new VarInsnNode(Opcodes.ALOAD, 3)); callCode.add(new InsnNode(Opcodes.ARETURN)); } coIteratorClass.methods.add(call); // if debugging code is emitted it needs space for two // additional locals and 5 stack operand if (generateDebugCode) { call.maxStack = 5; call.maxLocals = 5; } else { if (isStatic) { call.maxStack = 3; } else { call.maxStack = 4; } call.maxLocals = 3; } /* * CoIterator created - define it in the runtime and verify if * needed */ if (log.isLoggable(Level.FINEST)) { log.finest("Generated class " + coIteratorClassName); } ClassWriter cw = new ClassWriter(0); coIteratorClass.accept(cw); byte[] classBytes = cw.toByteArray(); try { CoroutineInstrumentator.dumpClass(coIteratorClassName, classBytes); } catch (IOException e) { throw new CoroutineGenerationException("Unable to write class " + coIteratorClassName, e); } /* * start generating method - new method is named as the method in * user code, it: returns instance of appropriate CoIterator (see * above), saves arguments of call */ if (log.isLoggable(Level.FINEST)) { log.finest("Instrumenting method " + coroutine.name); } InsnList code = coroutine.instructions; code.clear(); /* * create new Frame */ boolean isDebugFramePossible = generateDebugCode && coroutine.localVariables != null; if (isDebugFramePossible) { code.add(createDebugFrame(coroutine)); } else { code.add(createFrame(coroutine)); } /* * save frame in the first, and locals array in the second local * variable */ int argsSize = Type.getArgumentsAndReturnSizes(coroutine.desc) >> 2; if (isStatic) { argsSize -= 1; } code.add(new VarInsnNode(Opcodes.ASTORE, argsSize)); code.add(new VarInsnNode(Opcodes.ALOAD, argsSize)); code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLocals", "()[Ljava/lang/Object;")); int localsArrayIndex = argsSize + 1; code.add(new VarInsnNode(Opcodes.ASTORE, localsArrayIndex)); /* * save all call arguments (along with this if this method is not * static) into locals array */ Type[] argsTypes = Type.getArgumentTypes(coroutine.desc); if (!isStatic) { code.add(saveloc(localsArrayIndex, 0, 0, JAVA_LANG_OBJECT)); code.add(savelocs(localsArrayIndex, 1, 1, argsTypes)); } else { code.add(savelocs(localsArrayIndex, 0, 0, argsTypes)); } /* * create CoIterator instance with saved frame, make initial call to * next if needed and return to caller */ code.add(new TypeInsnNode(Opcodes.NEW, coIteratorClassName)); code.add(new InsnNode(Opcodes.DUP)); code.add(new VarInsnNode(Opcodes.ALOAD, argsSize)); code.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, coIteratorClassName, "<init>", CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR)); if (!getBoolean(annotation, "generator", true)) { code.add(new InsnNode(Opcodes.DUP)); code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, coIteratorClassName, "next", "()Ljava/lang/Object;")); code.add(new InsnNode(Opcodes.POP)); } code.add(new InsnNode(Opcodes.ARETURN)); /* * end method generation; maxs can be statically determined 3 * operands on stack (call to frame setLocals and CoIterator * constructor) + 1 if any argument is long or double (debug frame * needs 7 operands for variable names creation); locals = argsSize * + 1 reference to frame + 1 array of locals */ if (isDebugFramePossible) { coroutine.maxStack = 7; } else { boolean isCategory2ArgumentPresent = false; for (Type argType : argsTypes) { int sort = argType.getSort(); if (sort == Type.LONG || sort == Type.DOUBLE) { isCategory2ArgumentPresent = true; break; } } coroutine.maxStack = isCategory2ArgumentPresent ? 4 : 3; } coroutine.maxLocals = localsArrayIndex + 1; coroutine.localVariables.clear(); coroutine.tryCatchBlocks.clear(); num++; } }
From source file:pl.clareo.coroutines.core.CoroutineInstrumentator.java
License:Apache License
@Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (classBeingRedefined != null) { return null; }//from ww w . j a va 2s.c o m if (className.startsWith("java/") || className.startsWith("javax/") || className.startsWith("sun/")) { return null; } List<MethodNode> coroutineMethodsInCurrentClass; boolean debug = generateDebugCode; boolean print = printCode; boolean verify = runVerification; boolean outputBin = generateBinaryOutput; boolean asmComputeFrames = overrideFrames; if (!detectCoroutineClasses) { int classnameIndex = Arrays.binarySearch(coroutineEnabledClassnames, className); if (classnameIndex < 0) { // search package String packageName = className; int indexOfSlash; while ((indexOfSlash = packageName.lastIndexOf('/')) != -1) { packageName = packageName.substring(0, indexOfSlash); classnameIndex = Arrays.binarySearch(coroutineEnabledClassnames, packageName); if (classnameIndex >= 0) { break; } } if (classnameIndex < 0) return null; } debug = debugMode[classnameIndex]; print = printMode[classnameIndex]; verify = verifyMode[classnameIndex]; outputBin = outputBinMode[classnameIndex]; asmComputeFrames = overrideFramesMode[classnameIndex]; } boolean log = logger.isLoggable(Level.FINEST); if (log) { logger.finest(className + ": Analyzing"); } ClassReader asmClassReader = new ClassReader(classfileBuffer); ClassNode cn = new ClassNode(); asmClassReader.accept(cn, debug ? 0 : ClassReader.SKIP_DEBUG); ClassAnalyzer analyzer = new ClassAnalyzer(cn); analyzer.analyze(); coroutineMethodsInCurrentClass = analyzer.getCoroutineMethods(); if (coroutineMethodsInCurrentClass.isEmpty()) { return null; } if (log) { logger.finest(className + ": Instrumenting coroutines " + methodNodeListToString(coroutineMethodsInCurrentClass)); } ClassWriter asmClassWriter = new ClassWriter( (asmComputeFrames ? ClassWriter.COMPUTE_FRAMES : 0) | ClassWriter.COMPUTE_MAXS); ClassVisitor cv = asmClassWriter; byte[] instrumentedClassContents; try { if (print) { try { cv = createTracer(className, cv); } catch (FileNotFoundException e) { throw new CoroutineGenerationException("Unable to write trace file ", e); } } new ClassTransformer(cn, coroutineMethodsInCurrentClass, debug).transform(); cn.accept(cv); instrumentedClassContents = asmClassWriter.toByteArray(); if (verify) { verifyClass(className, new ClassReader(instrumentedClassContents), print); } if (outputBin) { dumpClass(className + "Instrumented", instrumentedClassContents); } } catch (IllegalStateException e) { logger.log(Level.WARNING, "Verification failed", e); return null; } catch (IllegalArgumentException e) { logger.log(Level.WARNING, "Verification failed", e); return null; } catch (CoroutineGenerationException e) { logger.warning(e.getMessage()); return null; } catch (Throwable t) { logger.log(Level.SEVERE, "Coroutine generation ended abruptly. This may be a bug in the package itself. Details below:", t); return null; } return instrumentedClassContents; }
From source file:portablejim.veinminer.asm.ItemInWorldManagerTransformer.java
License:Open Source License
public byte[] transformItemInWorldManager(String obfuscatedClassName, byte[] bytes) { ClassNode classNode = new ClassNode(); ClassReader classReader = new ClassReader(bytes); classReader.accept(classNode, 0);/*from www . ja va2s . c o m*/ // Setup type map for (FieldNode variable : classNode.fields) { String srgVariableName = FMLDeobfuscatingRemapper.INSTANCE.mapFieldName(obfuscatedClassName, variable.name, variable.desc); if (getCorrectName("theWorld").equals(srgVariableName) || getCorrectName("thisPlayerMP").equals(srgVariableName)) { typemap.put(srgVariableName, variable.desc); } } try { for (MethodNode curMethod : classNode.methods) { String srgFunctionName = FMLDeobfuscatingRemapper.INSTANCE.mapMethodName(obfuscatedClassName, curMethod.name, curMethod.desc); if (getCorrectName("uncheckedTryHarvestBlock").equals(srgFunctionName)) { Logger.debug("Inserting call to uncheckedTryHarvestBlock (%s)", srgFunctionName); insertCallAfterTryHarvestBlockFunction(curMethod, obfuscatedClassName); } else if (getCorrectName("onBlockClicked").equals(srgFunctionName)) { Logger.debug("Inserting call to onBlockClicked (%s)", srgFunctionName); int afterFirst = insertCallAfterTryHarvestBlockFunction(curMethod, obfuscatedClassName); insertCallAfterTryHarvestBlockFunction(curMethod, obfuscatedClassName, afterFirst); } } } catch (IndexOutOfBoundsException e) { FMLLog.getLogger().log(Level.WARNING, "[%s] Problem inserting all required code. This mod may not function correctly. Please report a bug.", ModInfo.MOD_NAME); } ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS); classNode.accept(writer); return writer.toByteArray(); }
From source file:pt.ist.esw.advice.GenerateAnnotationInstance.java
License:Open Source License
public void start() throws IOException { InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(annotation + ".class"); ClassReader cr = new ClassReader(is); ClassNode cNode = new ClassNode(); cr.accept(cNode, 0);/*from w w w . j ava 2s.c o m*/ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_6, ACC_PUBLIC | ACC_FINAL, annotationInstance, null, "java/lang/Object", new String[] { annotation }); cw.visitSource("Annotation Instance Class", null); // Generate fields for (MethodNode annotationElems : cNode.methods) { cw.visitField(ACC_PRIVATE | ACC_FINAL, annotationElems.name, getReturnTypeDescriptor(annotationElems), null, null); } // Generate constructor { StringBuffer ctorDescriptor = new StringBuffer("("); for (MethodNode annotationElems : cNode.methods) { ctorDescriptor.append(getReturnTypeDescriptor(annotationElems)); } ctorDescriptor.append(")V"); MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", ctorDescriptor.toString(), null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); int localsPos = 0; for (MethodNode annotationElems : cNode.methods) { Type t = Type.getReturnType(annotationElems.desc); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(t.getOpcode(ILOAD), localsPos + 1); mv.visitFieldInsn(PUTFIELD, annotationInstance, annotationElems.name, t.getDescriptor()); localsPos += t.getSize(); } mv.visitInsn(RETURN); mv.visitMaxs(0, 0); mv.visitEnd(); } // Generate getters for (MethodNode annotationElems : cNode.methods) { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, annotationElems.name, annotationElems.desc, null, null); mv.visitCode(); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn(GETFIELD, annotationInstance, annotationElems.name, getReturnTypeDescriptor(annotationElems)); mv.visitInsn(Type.getReturnType(annotationElems.desc).getOpcode(IRETURN)); mv.visitMaxs(0, 0); mv.visitEnd(); } // Generate annotationType() method { MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "annotationType", "()Ljava/lang/Class;", "()Ljava/lang/Class<+Ljava/lang/annotation/Annotation;>;", null); mv.visitCode(); mv.visitLdcInsn(Type.getType(annotationClass)); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } // Write Class FileOutputStream fos = null; try { File parentDir = new File(buildDir, ANNOTATION_INSTANCE_PACKAGE.replace('/', separatorChar)); if (!parentDir.exists() && !parentDir.mkdirs()) { throw new IOException("Could not create required directory: " + parentDir); } File f = new File(parentDir, annotationClass.getSimpleName() + "Instance.class"); fos = new FileOutputStream(f); fos.write(cw.toByteArray()); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } }