protected void injectGetIndex(ClassWriter classWriter) { MethodVisitor mv = classWriter.visitMethod(ACC_PRIVATE, "getIndex", "(Ljava/lang/String;)I", null, null); mv.visitCode(); mv.visitInsn(ICONST_0); mv.visitVarInsn(ISTORE, 2); Label forLoopLabel = new Label(); mv.visitLabel(forLoopLabel); mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null); mv.visitVarInsn(ILOAD, 2); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, getAccessorNameInternal(this.getTarget(), this.getAccessorType()), "fieldTable", "[Ljava/lang/reflect/Field;"); mv.visitInsn(ARRAYLENGTH); Label forLoopIncrementLabel = new Label(); mv.visitJumpInsn(IF_ICMPGE, forLoopIncrementLabel); mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, getAccessorNameInternal(this.getTarget(), this.getAccessorType()), "fieldTable", "[Ljava/lang/reflect/Field;"); mv.visitVarInsn(ILOAD, 2); mv.visitInsn(AALOAD); mv.visitMethodInsn( INVOKEVIRTUAL, "java/lang/reflect/Field", "getName", "()Ljava/lang/String;", false); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); Label equalsLabel = new Label(); mv.visitJumpInsn(IFEQ, equalsLabel); mv.visitVarInsn(ILOAD, 2); mv.visitInsn(IRETURN); mv.visitLabel(equalsLabel); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); mv.visitIincInsn(2, 1); mv.visitJumpInsn(GOTO, forLoopLabel); mv.visitLabel(forLoopIncrementLabel); mv.visitFrame(Opcodes.F_CHOP, 1, null, 0, null); mv.visitInsn(ICONST_M1); mv.visitInsn(IRETURN); mv.visitMaxs(2, 3); mv.visitEnd(); }
protected void injectConstructor(ClassWriter classWriter) { String resultName = getAccessorNameInternal(this.getTarget(), this.getAccessorType()); MethodVisitor methodVisitor = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); methodVisitor.visitCode(); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); ; methodVisitor.visitTypeInsn(NEW, "java/util/ArrayList"); methodVisitor.visitInsn(DUP); methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false); methodVisitor.visitVarInsn(ASTORE, 1); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, resultName, "getTargetClass", "()Ljava/lang/Class;", false); methodVisitor.visitVarInsn(ASTORE, 2); Label whileLoop = new Label(); // enter the "while (currentClass != Object.class)" loop methodVisitor.visitLabel(whileLoop); methodVisitor.visitFrame( Opcodes.F_FULL, 3, new Object[] {resultName, "java/util/List", "java/lang/Class"}, 0, new Object[] {}); methodVisitor.visitVarInsn(ALOAD, 2); methodVisitor.visitLdcInsn(Type.getType("Ljava/lang/Object;")); Label classNotObjectComparer = new Label(); // compares the current class to Object.class aka currentClass != Object.class methodVisitor.visitJumpInsn(IF_ACMPEQ, classNotObjectComparer); methodVisitor.visitVarInsn(ALOAD, 2); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getDeclaredFields", "()[Ljava/lang/reflect/Field;", false); methodVisitor.visitVarInsn(ASTORE, 3); methodVisitor.visitVarInsn(ALOAD, 3); methodVisitor.visitInsn(ARRAYLENGTH); methodVisitor.visitVarInsn(ISTORE, 4); methodVisitor.visitInsn(ICONST_0); methodVisitor.visitVarInsn(ISTORE, 5); Label cachingForLoop = new Label(); // this loop handles the storing of the fields (to the list) methodVisitor.visitLabel(cachingForLoop); methodVisitor.visitFrame( Opcodes.F_APPEND, 3, new Object[] {"[Ljava/lang/reflect/Field;", Opcodes.INTEGER, Opcodes.INTEGER}, 0, null); methodVisitor.visitVarInsn(ILOAD, 5); methodVisitor.visitVarInsn(ILOAD, 4); Label cachingForLoopIncrementLabel = new Label(); // handles the looping of the fields methodVisitor.visitJumpInsn(IF_ICMPGE, cachingForLoopIncrementLabel); methodVisitor.visitVarInsn(ALOAD, 3); methodVisitor.visitVarInsn(ILOAD, 5); methodVisitor.visitInsn(AALOAD); methodVisitor.visitVarInsn(ASTORE, 6); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitVarInsn(ALOAD, 6); methodVisitor.visitMethodInsn( INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true); methodVisitor.visitInsn(POP); methodVisitor.visitIincInsn(5, 1); methodVisitor.visitJumpInsn(GOTO, cachingForLoop); methodVisitor.visitLabel(cachingForLoopIncrementLabel); methodVisitor.visitFrame(Opcodes.F_CHOP, 3, null, 0, null); methodVisitor.visitVarInsn(ALOAD, 2); methodVisitor.visitMethodInsn( INVOKEVIRTUAL, "java/lang/Class", "getSuperclass", "()Ljava/lang/Class;", false); methodVisitor.visitVarInsn(ASTORE, 2); methodVisitor.visitJumpInsn(GOTO, whileLoop); methodVisitor.visitLabel(classNotObjectComparer); methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "size", "()I", true); methodVisitor.visitTypeInsn(ANEWARRAY, "java/lang/reflect/Field"); methodVisitor.visitFieldInsn(PUTFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;"); methodVisitor.visitInsn(ICONST_0); methodVisitor.visitVarInsn(ISTORE, 3); Label storingForLoop = new Label(); // this for loop goes about storing the fields in the array defined in the // class methodVisitor.visitLabel(storingForLoop); methodVisitor.visitFrame(Opcodes.F_APPEND, 1, new Object[] {Opcodes.INTEGER}, 0, null); methodVisitor.visitVarInsn(ILOAD, 3); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitFieldInsn(GETFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;"); methodVisitor.visitInsn(ARRAYLENGTH); Label storage = new Label(); // gets the field at position x and stores it in the cache (fieldTable) methodVisitor.visitJumpInsn(IF_ICMPGE, storage); methodVisitor.visitVarInsn(ALOAD, 0); methodVisitor.visitFieldInsn(GETFIELD, resultName, "fieldTable", "[Ljava/lang/reflect/Field;"); methodVisitor.visitVarInsn(ILOAD, 3); methodVisitor.visitVarInsn(ALOAD, 1); methodVisitor.visitVarInsn(ILOAD, 3); methodVisitor.visitMethodInsn( INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true); methodVisitor.visitTypeInsn(CHECKCAST, "java/lang/reflect/Field"); methodVisitor.visitInsn(AASTORE); methodVisitor.visitIincInsn(3, 1); methodVisitor.visitJumpInsn(GOTO, storingForLoop); methodVisitor.visitLabel(storage); methodVisitor.visitFrame(Opcodes.F_CHOP, 1, null, 0, null); methodVisitor.visitInsn(RETURN); methodVisitor.visitMaxs(4, 7); methodVisitor.visitEnd(); }