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();
  }