static ElementInfo getCheckedElementInfo(
      MJIEnv env, FieldInfo fi, int fobjRef, Class<?> fiType, String type) {
    ElementInfo ei;

    if (!isAvailable(env, fi, fobjRef)) {
      return null;
    }

    if (fi.isStatic()) {
      ei = fi.getClassInfo().getStaticElementInfo();
    } else { // instance field
      ei = env.getElementInfo(fobjRef);
    }

    // our guards (still need IllegalAccessException)
    if (ei == null) {
      env.throwException("java.lang.NullPointerException");
      return null;
    }
    if (fiType != null && !fiType.isInstance(fi)) {
      env.throwException(
          "java.lang.IllegalArgumentException", "field type incompatible with " + type);
      return null;
    }

    return ei;
  }
  @MJI
  public short parseShort__Ljava_lang_String_2I__S(
      MJIEnv env, int clsObjRef, int strRef, int radix, FeatureExpr ctx) {
    try {
      return Short.parseShort(env.getStringObject(ctx, strRef), radix);
    } catch (NumberFormatException e) {
      env.throwException(ctx, "java.lang.NumberFormatException");

      return 0;
    }
  }
  @MJI
  public int parseInt__Ljava_lang_String_2__I(
      MJIEnv env, int clsObjRef, int strRef, FeatureExpr ctx) {
    try {
      return Integer.parseInt(env.getStringObject(ctx, strRef));
    } catch (NumberFormatException e) {
      env.throwException(ctx, "java.lang.NumberFormatException");

      return 0;
    }
  }
 @MJI
 public byte readByte____B(MJIEnv env, int this_ptr, FeatureExpr ctx) {
   long current_posn = env.getLongField(this_ptr, current_position).getValue();
   long current_len = env.getLongField(this_ptr, current_length).getValue();
   int chunk_size = env.getStaticIntField(RandomAccessFile, CHUNK_SIZE);
   if (current_posn >= current_len) {
     env.throwException(ctx, EOFException);
   }
   int chunk = findDataChunk(env, this_ptr, current_posn, chunk_size, ctx);
   byte result = getDataValue(env, chunk, current_posn, chunk_size, ctx);
   env.setLongField(ctx, this_ptr, current_position, new One<>(current_posn + 1));
   return result;
 }
  /**
   * Peer method for the <code>java.lang.reflect.Field.set</code> method.
   *
   * @author Mirko Stojmenovic ([email protected])
   * @author Igor Andjelkovic ([email protected])
   * @author Milos Gligoric ([email protected])
   */
  public static void set__Ljava_lang_Object_2Ljava_lang_Object_2__V(
      MJIEnv env, int objRef, int fobjRef, int val) {
    FieldInfo fi = getFieldInfo(env, objRef);
    int modifiers = fi.getModifiers();

    if (!isAvailable(env, fi, fobjRef)) {
      return;
    }

    if (Modifier.isFinal(modifiers)) {
      env.throwException("java.lang.IllegalAccessException", "field " + fi.getName() + " is final");
      return;
    }
    ClassInfo ci = fi.getClassInfo();
    ClassInfo cio = env.getClassInfo(fobjRef);

    if (!fi.isStatic() && !cio.isInstanceOf(ci)) {
      env.throwException(
          "java.lang.IllegalArgumentException",
          fi.getType() + "field " + fi.getName() + " does not belong to this object");
      return;
    }

    Object[] attrs = env.getArgAttributes();
    Object attr = (attrs == null) ? null : attrs[2];

    if (!setValue(env, fi, fobjRef, val, attr)) {
      env.throwException(
          "java.lang.IllegalArgumentException",
          "Can not set "
              + fi.getType()
              + " field "
              + fi.getFullName()
              + " to "
              + ((MJIEnv.NULL != val) ? env.getClassInfo(val).getName() + " object " : "null"));
    }
  }
  @MJI
  public int get__Ljava_lang_Object_2__Ljava_lang_Object_2(
      MJIEnv env, int objRef, int fobjRef, FeatureExpr ctx) {
    FieldInfo fi = getFieldInfo(ctx, env, objRef);
    ElementInfo ei =
        getCheckedElementInfo(
            env, objRef, fi, fobjRef, null, null, false, ctx); // no type check here
    if (ei == null) {
      return 0;
    }

    if (!(fi instanceof ReferenceFieldInfo)) { // primitive type, we need to box it
      if (fi instanceof DoubleFieldInfo) {
        Conditional<Double> d = ei.getDoubleField(fi);
        return env.newDouble(ctx, d);
      } else if (fi instanceof FloatFieldInfo) {
        Conditional<Float> f = ei.getFloatField(fi);
        return env.newFloat(ctx, f);
      } else if (fi instanceof LongFieldInfo) {
        Conditional<Long> l = ei.getLongField(fi);
        return env.newLong(ctx, l);
      } else if (fi instanceof IntegerFieldInfo) {
        // this might actually represent a plethora of types
        Conditional<Integer> i = ei.getIntField(fi);
        return env.newInteger(ctx, i);
      } else if (fi instanceof BooleanFieldInfo) {
        Conditional<Boolean> b = ei.getBooleanField(fi);
        return env.newBoolean(b.getValue());
      } else if (fi instanceof ByteFieldInfo) {
        Conditional<Byte> z = ei.getByteField(fi);
        return env.newByte(ctx, z);
      } else if (fi instanceof CharFieldInfo) {
        Conditional<Character> c = ei.getCharField(fi);
        return env.newCharacter(ctx, c);
      } else if (fi instanceof ShortFieldInfo) {
        Conditional<Short> s = ei.getShortField(fi);
        return env.newShort(ctx, s);
      }

    } else { // it's a reference
      int ref = ei.getReferenceField(fi).simplify(ctx).getValue(); // we internally store it as int
      return ref;
    }

    env.throwException(ctx, "java.lang.IllegalArgumentException", "unknown field type");
    return MJIEnv.NULL;
  }
  /** >2do> that doesn't take care of class init yet */
  public static int getType____Ljava_lang_Class_2(MJIEnv env, int objRef) {
    ThreadInfo ti = env.getThreadInfo();
    FieldInfo fi = getFieldInfo(env, objRef);

    try {
      ClassInfo ci = fi.getTypeClassInfo();
      if (!ci.isRegistered()) {
        ci.registerClass(ti);
      }

      return ci.getClassObjectRef();

    } catch (NoClassInfoException cx) {
      env.throwException("java.lang.NoClassDefFoundError", cx.getMessage());
      return MJIEnv.NULL;
    }
  }
  static boolean isAvailable(MJIEnv env, FieldInfo fi, int fobjRef) {
    if (fi.isStatic()) {
      ClassInfo fci = fi.getClassInfo();
      if (fci.requiresClinitExecution(env.getThreadInfo())) {
        env.repeatInvocation();
        return false;
      }

    } else {
      if (fobjRef == MJIEnv.NULL) {
        env.throwException("java.lang.NullPointerException");
        return false;
      }
      // class had obviously been initialized, otherwise we won't have an instance of it
    }

    return true;
  }
  public static int get__Ljava_lang_Object_2__Ljava_lang_Object_2(
      MJIEnv env, int objRef, int fobjRef) {
    FieldInfo fi = getFieldInfo(env, objRef);
    ElementInfo ei = getCheckedElementInfo(env, fi, fobjRef, null, null); // no type check here
    if (ei == null) {
      return 0;
    }

    if (!(fi instanceof ReferenceFieldInfo)) { // primitive type, we need to box it
      if (fi instanceof DoubleFieldInfo) {
        double d = ei.getDoubleField(fi);
        return env.newDouble(d);
      } else if (fi instanceof FloatFieldInfo) {
        float f = ei.getFloatField(fi);
        return env.newFloat(f);
      } else if (fi instanceof LongFieldInfo) {
        long l = ei.getLongField(fi);
        return env.newLong(l);
      } else if (fi instanceof IntegerFieldInfo) {
        // this might actually represent a plethora of types
        int i = ei.getIntField(fi);
        return env.newInteger(i);
      } else if (fi instanceof BooleanFieldInfo) {
        boolean b = ei.getBooleanField(fi);
        return env.newBoolean(b);
      } else if (fi instanceof ByteFieldInfo) {
        byte z = ei.getByteField(fi);
        return env.newByte(z);
      } else if (fi instanceof CharFieldInfo) {
        char c = ei.getCharField(fi);
        return env.newCharacter(c);
      } else if (fi instanceof ShortFieldInfo) {
        short s = ei.getShortField(fi);
        return env.newShort(s);
      }

    } else { // it's a reference
      int ref = ei.getReferenceField(fi); // we internally store it as int
      return ref;
    }

    env.throwException("java.lang.IllegalArgumentException", "unknown field type");
    return MJIEnv.NULL;
  }
  private static boolean setValue(MJIEnv env, FieldInfo fi, int obj, int value, Object attr) {
    ClassInfo fieldClassInfo = fi.getClassInfo();

    String className = fieldClassInfo.getName();
    String fieldType = fi.getType();

    try {
      ClassInfo tci = fi.getTypeClassInfo();

      if (tci.isPrimitive()) {
        if (value == MJIEnv.NULL) {
          return false;
        }

        // checks whether unboxing can be done by accessing the field "value"
        final String fieldName = "value";
        FieldInfo finfo = env.getElementInfo(value).getFieldInfo(fieldName);
        if (finfo == null) {
          return false;
        }

        ElementInfo ei =
            fi.isStatic() ? fi.getClassInfo().getStaticElementInfo() : env.getElementInfo(obj);
        ei.setFieldAttr(fi, attr);

        if ("boolean".equals(fieldType)) {
          boolean val = env.getBooleanField(value, fieldName);
          ei.setBooleanField(fi, val);
          return true;
        } else if ("byte".equals(fieldType)) {
          byte val = env.getByteField(value, fieldName);
          ei.setByteField(fi, val);
          return true;
        } else if ("char".equals(fieldType)) {
          char val = env.getCharField(value, fieldName);
          ei.setCharField(fi, val);
          return true;
        } else if ("short".equals(fieldType)) {
          short val = env.getShortField(value, fieldName);
          ei.setShortField(fi, val);
          return true;
        } else if ("int".equals(fieldType)) {
          int val = env.getIntField(value, fieldName);
          ei.setIntField(fi, val);
          return true;
        } else if ("long".equals(fieldType)) {
          long val = env.getLongField(value, fieldName);
          ei.setLongField(fi, val);
          return true;
        } else if ("float".equals(fieldType)) {
          float val = env.getFloatField(value, fieldName);
          ei.setFloatField(fi, val);
          return true;
        } else if ("double".equals(fieldType)) {
          double val = env.getDoubleField(value, fieldName);
          ei.setDoubleField(fi, val);
          return true;
        } else {
          return false;
        }

      } else { // it's a reference
        if (value != MJIEnv.NULL) {
          String type = env.getTypeName(value);
          // this is an instance so the ClassInfo has to be registered
          ClassInfo valueCI = ClassInfo.getResolvedClassInfo(type);
          if (!valueCI.isInstanceOf(tci)) {
            return false;
          }
        }

        ElementInfo ei =
            fi.isStatic() ? fi.getClassInfo().getStaticElementInfo() : env.getElementInfo(obj);
        ei.setFieldAttr(fi, attr);

        if (fi.isStatic()) {
          env.setStaticReferenceField(className, fi.getName(), value);
        } else {
          env.setReferenceField(obj, fi.getName(), value);
        }
        return true;
      }

    } catch (NoClassInfoException cx) {
      env.throwException("java.lang.NoClassDefFoundError", cx.getMessage());
      return false;
    }
  }
  static ElementInfo getCheckedElementInfo(
      MJIEnv env,
      int objRef,
      FieldInfo fi,
      int fobjRef,
      Class<?> fiType,
      String type,
      boolean isWrite,
      FeatureExpr ctx) {
    ElementInfo ei;

    if (!isAvailable(env, fi, fobjRef, ctx)) {
      return null;
    }

    if (fi.isStatic()) {
      ClassInfo fci = fi.getClassInfo();
      ei = isWrite ? fci.getModifiableStaticElementInfo() : fci.getStaticElementInfo();
    } else { // instance field
      ei = isWrite ? env.getModifiableElementInfo(fobjRef) : env.getElementInfo(fobjRef);
    }

    // our guards (still need IllegalAccessException)
    if (fi.isPrivate() && !env.getBooleanField(objRef, "isAccessible").getValue()) {
      env.throwException(ctx, IllegalAccessException.class.getName(), fi + "");
      return null;
    }

    if (ei == null) {
      env.throwException(ctx, "java.lang.NullPointerException");
      return null;
    }
    if (fiType != null) {
      if (fiType == ByteFieldInfo.class) {
        if (fi.isByteField()) {
          return ei;
        }
      } else if (fiType == ShortFieldInfo.class) {
        if (fi.isShortField()) {
          return ei;
        }
      } else if (fiType == IntegerFieldInfo.class) {
        if (fi.isIntField()) {
          return ei;
        }
      } else if (fiType == LongFieldInfo.class) {
        if (fi.isLongField()) {
          return ei;
        }
      } else if (fiType == FloatFieldInfo.class) {
        if (fi.isFloatField()) {
          return ei;
        }
      }
      if (!fiType.isInstance(fi)) {
        env.throwException(
            ctx,
            "java.lang.IllegalArgumentException",
            "field type " + fi.getType() + " incompatible with " + type);
        return null;
      }
    }

    return ei;
  }
  /**
   * Peer method for the <code>java.lang.reflect.Field.set</code> method.
   *
   * @author Mirko Stojmenovic ([email protected])
   * @author Igor Andjelkovic ([email protected])
   * @author Milos Gligoric ([email protected])
   */
  @MJI
  public void set__Ljava_lang_Object_2Ljava_lang_Object_2__V(
      MJIEnv env, int objRef, int fobjRef, int val, FeatureExpr ctx) {
    FieldInfo fi = getFieldInfo(ctx, env, objRef);
    if (!isAvailable(env, fi, fobjRef, ctx)) {
      return;
    }

    if (fi.isFinal() && fi.isStatic()) {
      env.throwException(
          ctx,
          IllegalAccessException.class.getName(),
          "Can not set static final " + fi.getType() + " field " + fi.getFullName());
      return;
    }
    if (!env.getBooleanField(objRef, "isAccessible").getValue() && fi.isFinal()) {
      env.throwException(
          ctx,
          IllegalAccessException.class.getName(),
          "Can not set final " + fi.getType() + " field " + fi.getFullName());
      return;
    }

    ClassInfo ci = fi.getClassInfo();
    ClassInfo cio = env.getClassInfo(fobjRef);
    if (!fi.isStatic() && !cio.isInstanceOf(ci)) {
      env.throwException(
          ctx,
          IllegalAccessException.class.getName(),
          fi.getType() + "field " + fi.getName() + " does not belong to this object");
      return;
    }

    if (!env.getBooleanField(objRef, "isAccessible").getValue()) {
      if (!fi.isStatic() && cio.isInstanceOf(ci)) {
        if (!fi.isPublic()) {
          env.throwException(
              ctx, IllegalAccessException.class.getName(), fi.getType() + " field " + fi.getName());
          return;
        }
      } else {
        if (!fi.isPublic()) {
          env.throwException(
              ctx, IllegalAccessException.class.getName(), fi.getType() + " field " + fi.getName());
          return;
        }
      }
    }

    Object[] attrs = env.getArgAttributes();
    Object attr = (attrs == null) ? null : attrs[2];

    if (!setValue(ctx, env, fi, fobjRef, val, attr)) {
      env.throwException(
          ctx,
          IllegalAccessException.class.getName(),
          "Can not set "
              + fi.getType()
              + " field "
              + fi.getFullName()
              + " to "
              + ((MJIEnv.NULL != val) ? env.getClassInfo(val).getName() + " object " : "null"));
    }
  }