protected void injectGetByIndex(
      ClassWriter classWriter, String targetClassName, List<Field> fields) {
    MethodVisitor methodVisitor =
        classWriter.visitMethod(
            ACC_PUBLIC,
            "get",
            "(Ljava/lang/Object;I)Ljava/lang/Object;",
            null,
            new String[] {getInternalName(ILLEGAL_ACCESS_EXCEPTION.getCanonicalName())});

    Boxer boxer = new Boxer(methodVisitor);

    methodVisitor.visitCode();
    methodVisitor.visitVarInsn(ILOAD, 2);

    int maxStack = 6;

    Label[] labels = new Label[fields.size()];
    Label errorLabel = new Label();

    for (int i = 0; i < fields.size(); i++) {
      labels[i] = new Label();
    }

    methodVisitor.visitTableSwitchInsn(0, labels.length - 1, errorLabel, labels);

    if (!fields.isEmpty()) {
      maxStack--;

      for (int i = 0; i < fields.size(); i++) {
        Field field = fields.get(i);
        Class<?> type = field.getType();
        String fieldDescriptor = Type.getDescriptor(type);

        methodVisitor.visitLabel(labels[i]);

        if (i == 0) methodVisitor.visitFrame(F_APPEND, 1, new Object[] {targetClassName}, 0, null);
        else methodVisitor.visitFrame(F_SAME, 0, null, 0, null);

        if (isPublic(field)) {
          methodVisitor.visitVarInsn(ALOAD, 1);
          methodVisitor.visitTypeInsn(CHECKCAST, targetClassName);
          methodVisitor.visitFieldInsn(GETFIELD, targetClassName, field.getName(), fieldDescriptor);

          boxer.box(Type.getType(type));
        } else {
          injectReflectiveGetter(methodVisitor);
        }

        methodVisitor.visitInsn(ARETURN);
      }

      methodVisitor.visitLabel(errorLabel);
      methodVisitor.visitFrame(F_SAME, 0, null, 0, null);
    }

    injectException(methodVisitor, IllegalAccessException.class);
    methodVisitor.visitMaxs(maxStack, 3);
    methodVisitor.visitEnd();
  }
 protected void injectException(
     MethodVisitor methodVisitor, Class<? extends Throwable> throwable) {
   methodVisitor.visitTypeInsn(NEW, getInternalName(throwable.getCanonicalName()));
   methodVisitor.visitInsn(DUP);
   methodVisitor.visitTypeInsn(NEW, "java/lang/StringBuilder");
   methodVisitor.visitInsn(DUP);
   methodVisitor.visitLdcInsn("Invalid index: ");
   methodVisitor.visitMethodInsn(
       INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V");
   methodVisitor.visitVarInsn(ILOAD, 2);
   methodVisitor.visitMethodInsn(
       INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;");
   methodVisitor.visitMethodInsn(
       INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;");
   methodVisitor.visitMethodInsn(
       INVOKESPECIAL,
       getInternalName(throwable.getCanonicalName()),
       "<init>",
       "(Ljava/lang/String;)V");
   methodVisitor.visitInsn(ATHROW);
 }
 protected static String toSafeName(Class<?> clazz) {
   return clazz.getCanonicalName().replace("[]", "Array").replace(".", "_");
 }