Field reflection.

Change-Id: I10ffddbbc20cb5b4bbe7df52fef721e12f4b852c
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 6b4c5c0..31a39c3 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -805,6 +805,28 @@
   EXPECT_EQ(16U, data_offset - array_offset);
 }
 
+TEST_F(ClassLinkerTest, ValidateBoxedTypes) {
+  // Validate that the "value" field is always the 0th field in each of java.lang's box classes.
+  // This lets UnboxPrimitive avoid searching for the field by name at runtime.
+  Class* c;
+  c = class_linker_->FindClass("Ljava/lang/Boolean;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Byte;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Character;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Double;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Float;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Integer;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Long;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+  c = class_linker_->FindClass("Ljava/lang/Short;", NULL);
+  EXPECT_EQ("value", c->GetIFields()->Get(0)->GetName()->ToModifiedUtf8());
+}
+
 TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
   const ClassLoader* class_loader_1 = LoadDex("MyClass");
   const ClassLoader* class_loader_2 = LoadDex("MyClass");
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index 528c09f..d73a7af 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -28,35 +28,540 @@
   return Decode<Object*>(env, jfield)->AsField()->GetAccessFlags() & kAccFieldFlagsMask;
 }
 
+// TODO: we'll need this for Method too.
+bool VerifyObjectInClass(JNIEnv* env, Object* o, Class* c) {
+  if (o == NULL) {
+    jniThrowNullPointerException(env, "receiver for non-static field access was null");
+    return false;
+  }
+  if (!o->InstanceOf(c)) {
+    std::string expectedClassName(PrettyDescriptor(c->GetDescriptor()));
+    std::string actualClassName(PrettyTypeOf(o));
+    jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+        "expected receiver of type %s, but got %s",
+        expectedClassName.c_str(), actualClassName.c_str());
+    return false;
+  }
+  return true;
+}
+
+/*
+ * Convert primitive, boxed data from "srcPtr" to "dstPtr".
+ *
+ * Section v2 2.6 lists the various conversions and promotions.  We
+ * allow the "widening" and "identity" conversions, but don't allow the
+ * "narrowing" conversions.
+ *
+ * Allowed:
+ *  byte to short, int, long, float, double
+ *  short to int, long, float double
+ *  char to int, long, float, double
+ *  int to long, float, double
+ *  long to float, double
+ *  float to double
+ * Values of types byte, char, and short are "internally" widened to int.
+ *
+ * Returns the width in 32-bit words of the destination primitive, or
+ * -1 if the conversion is not allowed.
+ */
+bool ConvertPrimitiveValue(Class* src_class, Class* dst_class, const JValue& src, JValue& dst) {
+  Class::PrimitiveType srcType = src_class->GetPrimitiveType();
+  Class::PrimitiveType dstType = dst_class->GetPrimitiveType();
+  switch (dstType) {
+  case Class::kPrimBoolean:
+  case Class::kPrimChar:
+  case Class::kPrimByte:
+    if (srcType == dstType) {
+      dst.i = src.i;
+      return true;
+    }
+    break;
+  case Class::kPrimShort:
+    if (srcType == Class::kPrimByte || srcType == Class::kPrimShort) {
+      dst.i = src.i;
+      return true;
+    }
+    break;
+  case Class::kPrimInt:
+    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
+        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+      dst.i = src.i;
+      return true;
+    }
+    break;
+  case Class::kPrimLong:
+    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
+        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+      dst.j = src.i;
+      return true;
+    } else if (srcType == Class::kPrimLong) {
+      dst.j = src.j;
+      return true;
+    }
+    break;
+  case Class::kPrimFloat:
+    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
+        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+      dst.f = src.i;
+      return true;
+    } else if (srcType == Class::kPrimLong) {
+      dst.f = src.j;
+      return true;
+    } else if (srcType == Class::kPrimFloat) {
+      dst.i = src.i;
+      return true;
+    }
+    break;
+  case Class::kPrimDouble:
+    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
+        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+      dst.d = src.i;
+      return true;
+    } else if (srcType == Class::kPrimLong) {
+      dst.d = src.j;
+      return true;
+    } else if (srcType == Class::kPrimFloat) {
+      dst.d = src.f;
+      return true;
+    } else if (srcType == Class::kPrimDouble) {
+      dst.j = src.j;
+      return true;
+    }
+    break;
+  default:
+    break;
+  }
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+      "invalid primitive conversion from %s to %s",
+      PrettyDescriptor(src_class->GetDescriptor()).c_str(),
+      PrettyDescriptor(dst_class->GetDescriptor()).c_str());
+  return false;
+}
+
+bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value) {
+  if (dst_class->GetPrimitiveType() == Class::kPrimNot) {
+    if (o != NULL && !o->InstanceOf(dst_class)) {
+      jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+          "expected object of type %s, but got %s",
+          PrettyDescriptor(dst_class->GetDescriptor()).c_str(),
+          PrettyTypeOf(o).c_str());
+      return false;
+    }
+    unboxed_value.l = o;
+    return true;
+  } else if (dst_class->GetPrimitiveType() == Class::kPrimVoid) {
+    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+        "can't unbox to void");
+    return false;
+  }
+
+  if (o == NULL) {
+    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+        "null passed for boxed primitive type");
+    return false;
+  }
+
+  JValue boxed_value = { 0 };
+  const String* src_descriptor = o->GetClass()->GetDescriptor();
+  Class* src_class = NULL;
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Field* primitive_field = o->GetClass()->GetIFields()->Get(0);
+  if (src_descriptor->Equals("Ljava/lang/Boolean;")) {
+    src_class = class_linker->FindPrimitiveClass('Z');
+    boxed_value.z = primitive_field->GetBoolean(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Byte;")) {
+    src_class = class_linker->FindPrimitiveClass('B');
+    boxed_value.b = primitive_field->GetByte(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Character;")) {
+    src_class = class_linker->FindPrimitiveClass('C');
+    boxed_value.c = primitive_field->GetChar(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Float;")) {
+    src_class = class_linker->FindPrimitiveClass('F');
+    boxed_value.f = primitive_field->GetFloat(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Double;")) {
+    src_class = class_linker->FindPrimitiveClass('D');
+    boxed_value.d = primitive_field->GetDouble(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Integer;")) {
+    src_class = class_linker->FindPrimitiveClass('I');
+    boxed_value.i = primitive_field->GetInt(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Long;")) {
+    src_class = class_linker->FindPrimitiveClass('J');
+    boxed_value.j = primitive_field->GetLong(o);
+  } else if (src_descriptor->Equals("Ljava/lang/Short;")) {
+    src_class = class_linker->FindPrimitiveClass('S');
+    boxed_value.s = primitive_field->GetShort(o);
+  } else {
+    Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+        "%s is not a boxed primitive type", PrettyDescriptor(src_descriptor).c_str());
+    return false;
+  }
+
+  return ConvertPrimitiveValue(src_class, dst_class, boxed_value, unboxed_value);
+}
+
+Method* gBoolean_valueOf;
+Method* gByte_valueOf;
+Method* gCharacter_valueOf;
+Method* gDouble_valueOf;
+Method* gFloat_valueOf;
+Method* gInteger_valueOf;
+Method* gLong_valueOf;
+Method* gShort_valueOf;
+
+void InitBoxingMethod(Method*& m, const char* class_descriptor, const char* method_signature) {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  Class* c = class_linker->FindSystemClass(class_descriptor);
+  CHECK(c != NULL) << "Couldn't find boxing class: " << class_descriptor;
+  m = c->FindDirectMethod("valueOf", method_signature);
+  CHECK(m != NULL) << "Couldn't find boxing method: " << method_signature;
+}
+
+void BoxPrimitive(JNIEnv* env, Class* src_class, JValue& value) {
+  if (!src_class->IsPrimitive()) {
+    return;
+  }
+
+  Method* m = NULL;
+  UniquePtr<byte[]> args(new byte[8]);
+  memset(&args[0], 0, 8);
+  switch (src_class->GetPrimitiveType()) {
+  case Class::kPrimBoolean:
+    m = gBoolean_valueOf;
+    *reinterpret_cast<uint32_t*>(&args[0]) = value.z;
+    break;
+  case Class::kPrimByte:
+    m = gByte_valueOf;
+    *reinterpret_cast<uint32_t*>(&args[0]) = value.b;
+    break;
+  case Class::kPrimChar:
+    m = gCharacter_valueOf;
+    *reinterpret_cast<uint32_t*>(&args[0]) = value.c;
+    break;
+  case Class::kPrimDouble:
+    m = gDouble_valueOf;
+    *reinterpret_cast<double*>(&args[0]) = value.d;
+    break;
+  case Class::kPrimFloat:
+    m = gFloat_valueOf;
+    *reinterpret_cast<float*>(&args[0]) = value.f;
+    break;
+  case Class::kPrimInt:
+    m = gInteger_valueOf;
+    *reinterpret_cast<uint32_t*>(&args[0]) = value.i;
+    break;
+  case Class::kPrimLong:
+    m = gLong_valueOf;
+    *reinterpret_cast<uint64_t*>(&args[0]) = value.j;
+    break;
+  case Class::kPrimShort:
+    m = gShort_valueOf;
+    *reinterpret_cast<uint32_t*>(&args[0]) = value.s;
+    break;
+  default:
+    LOG(FATAL) << PrettyClass(src_class);
+  }
+
+  Thread* self = Thread::Current();
+  ScopedThreadStateChange tsc(self, Thread::kRunnable);
+  m->Invoke(self, NULL, args.get(), &value);
+}
+
+bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
+  switch (f->GetType()->GetPrimitiveType()) {
+  case Class::kPrimBoolean:
+    value.z = f->GetBoolean(o);
+    return true;
+  case Class::kPrimByte:
+    value.b = f->GetByte(o);
+    return true;
+  case Class::kPrimChar:
+    value.c = f->GetChar(o);
+    return true;
+  case Class::kPrimDouble:
+    value.d = f->GetDouble(o);
+    return true;
+  case Class::kPrimFloat:
+    value.f = f->GetFloat(o);
+    return true;
+  case Class::kPrimInt:
+    value.i = f->GetInt(o);
+    return true;
+  case Class::kPrimLong:
+    value.j = f->GetLong(o);
+    return true;
+  case Class::kPrimShort:
+    value.s = f->GetShort(o);
+    return true;
+  case Class::kPrimNot:
+    if (allow_references) {
+      value.l = f->GetObject(o);
+      return true;
+    }
+    // Else break to report an error.
+    break;
+  case Class::kPrimVoid:
+    // Never okay.
+    break;
+  }
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+      "Not a primitive field: %s", PrettyField(f).c_str());
+  return false;
+}
+
+JValue GetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jchar targetDescriptor) {
+  Field* f = reinterpret_cast<Field*>(env->FromReflectedField(javaField));
+
+  // Check that the receiver is non-null and an instance of the field's declaring class.
+  Object* o = Decode<Object*>(env, javaObj);
+  bool isStatic = (javaObj == NULL);
+  if (!isStatic) {
+    Class* declaringClass = Decode<Class*>(env, javaDeclaringClass);
+    if (!VerifyObjectInClass(env, o, declaringClass)) {
+      return JValue();
+    }
+  }
+
+  // Read the value.
+  JValue field_value;
+  if (!GetFieldValue(o, f, field_value, false)) {
+    return JValue();
+  }
+
+  // Widen it if necessary (and possible).
+  JValue wide_value;
+  Class* targetType = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(targetDescriptor);
+  if (!ConvertPrimitiveValue(f->GetType(), targetType, field_value, wide_value)) {
+    return JValue();
+  }
+  return wide_value;
+}
+
+jbyte Field_getBField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).b;
+}
+
+jchar Field_getCField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).c;
+}
+
+jdouble Field_getDField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).d;
+}
+
+jfloat Field_getFField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).f;
+}
+
+jint Field_getIField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).i;
+}
+
+jlong Field_getJField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).j;
+}
+
+jshort Field_getSField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).s;
+}
+
+jboolean Field_getZField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor) {
+  return GetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor).z;
+}
+
+void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool allow_references) {
+  switch (f->GetType()->GetPrimitiveType()) {
+  case Class::kPrimBoolean:
+    f->SetBoolean(o, new_value.z);
+    return;
+  case Class::kPrimByte:
+    f->SetByte(o, new_value.b);
+    return;
+  case Class::kPrimChar:
+    f->SetChar(o, new_value.c);
+    return;
+  case Class::kPrimDouble:
+    f->SetDouble(o, new_value.d);
+    return;
+  case Class::kPrimFloat:
+    f->SetFloat(o, new_value.f);
+    return;
+  case Class::kPrimInt:
+    f->SetInt(o, new_value.i);
+    return;
+  case Class::kPrimLong:
+    f->SetLong(o, new_value.j);
+    return;
+  case Class::kPrimShort:
+    f->SetShort(o, new_value.s);
+    return;
+  case Class::kPrimNot:
+    if (allow_references) {
+      f->SetObject(o, new_value.l);
+      return;
+    }
+    // Else break to report an error.
+    break;
+  case Class::kPrimVoid:
+    // Never okay.
+    break;
+  }
+  Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
+      "Not a primitive field: %s", PrettyField(f).c_str());
+}
+
+void SetPrimitiveField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jchar targetDescriptor, const JValue& new_value) {
+  Field* f = reinterpret_cast<Field*>(env->FromReflectedField(javaField));
+
+  // Check that the receiver is non-null and an instance of the field's declaring class.
+  Object* o = Decode<Object*>(env, javaObj);
+  bool isStatic = (javaObj == NULL);
+  if (!isStatic) {
+    Class* declaringClass = Decode<Class*>(env, javaDeclaringClass);
+    if (!VerifyObjectInClass(env, o, declaringClass)) {
+      return;
+    }
+  }
+
+  // Widen the value if necessary (and possible).
+  JValue wide_value;
+  Class* targetType = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(targetDescriptor);
+  if (!ConvertPrimitiveValue(f->GetType(), targetType, new_value, wide_value)) {
+    return;
+  }
+
+  // Write the value.
+  SetFieldValue(o, f, wide_value, false);
+}
+
+void Field_setBField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jbyte value) {
+  JValue v = { 0 };
+  v.b = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setCField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jchar value) {
+  JValue v = { 0 };
+  v.c = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setDField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jdouble value) {
+  JValue v = { 0 };
+  v.d = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setFField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jfloat value) {
+  JValue v = { 0 };
+  v.f = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setIField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jint value) {
+  JValue v = { 0 };
+  v.i = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setJField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jlong value) {
+  JValue v = { 0 };
+  v.j = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setSField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jshort value) {
+  JValue v = { 0 };
+  v.s = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setZField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jchar targetDescriptor, jboolean value) {
+  JValue v = { 0 };
+  v.z = value;
+  SetPrimitiveField(env, javaField, javaObj, javaDeclaringClass, targetDescriptor, v);
+}
+
+void Field_setField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean, jobject javaValue) {
+  Field* f = reinterpret_cast<Field*>(env->FromReflectedField(javaField));
+
+  // Unbox the value, if necessary.
+  Object* boxed_value = Decode<Object*>(env, javaValue);
+  JValue unboxed_value;
+  if (!UnboxPrimitive(env, boxed_value, f->GetType(), unboxed_value)) {
+    return;
+  }
+
+  // Check that the receiver is non-null and an instance of the field's declaring class.
+  Object* o = Decode<Object*>(env, javaObj);
+  bool isStatic = (javaObj == NULL);
+  if (!isStatic) {
+    Class* declaringClass = Decode<Class*>(env, javaDeclaringClass);
+    if (!VerifyObjectInClass(env, o, declaringClass)) {
+      return;
+    }
+  }
+
+  SetFieldValue(o, f, unboxed_value, true);
+}
+
+jobject Field_getField(JNIEnv* env, jobject javaField, jobject javaObj, jclass javaDeclaringClass, jclass, jint, jboolean) {
+  Field* f = reinterpret_cast<Field*>(env->FromReflectedField(javaField));
+
+  // Check that the receiver is non-null and an instance of the field's declaring class.
+  Object* o = Decode<Object*>(env, javaObj);
+  bool isStatic = (javaObj == NULL);
+  if (!isStatic) {
+    Class* declaringClass = Decode<Class*>(env, javaDeclaringClass);
+    if (!VerifyObjectInClass(env, o, declaringClass)) {
+      return NULL;
+    }
+  }
+
+  // Get the field's value, boxing if necessary.
+  JValue value;
+  if (!GetFieldValue(o, f, value, true)) {
+    return NULL;
+  }
+  BoxPrimitive(env, f->GetType(), value);
+
+  return AddLocalReference<jobject>(env, value.l);
+}
+
 static JNINativeMethod gMethods[] = {
-  //NATIVE_METHOD(Field, getAnnotation, "(Ljava/lang/Class;ILjava/lang/Class;)Ljava/lang/annotation/Annotation;"),
-  //NATIVE_METHOD(Field, getBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B"),
-  //NATIVE_METHOD(Field, getCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C"),
-  //NATIVE_METHOD(Field, getDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D"),
-  //NATIVE_METHOD(Field, getDeclaredAnnotations, "(Ljava/lang/Class;I)[Ljava/lang/annotation/Annotation;"),
-  //NATIVE_METHOD(Field, getFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F"),
-  //NATIVE_METHOD(Field, getField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;"),
-  NATIVE_METHOD(Field, getFieldModifiers, "(Ljava/lang/Class;I)I"),
-  //NATIVE_METHOD(Field, getIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I"),
-  //NATIVE_METHOD(Field, getJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J"),
-  //NATIVE_METHOD(Field, getSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S"),
   //NATIVE_METHOD(Field, getSignatureAnnotation, "(Ljava/lang/Class;I)[Ljava/lang/Object;"),
-  //NATIVE_METHOD(Field, getZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z"),
-  //NATIVE_METHOD(Field, isAnnotationPresent, "(Ljava/lang/Class;ILjava/lang/Class;)Z"),
-  //NATIVE_METHOD(Field, setBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V"),
-  //NATIVE_METHOD(Field, setCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V"),
-  //NATIVE_METHOD(Field, setDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V"),
-  //NATIVE_METHOD(Field, setFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V"),
-  //NATIVE_METHOD(Field, setField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V"),
-  //NATIVE_METHOD(Field, setIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V"),
-  //NATIVE_METHOD(Field, setJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V"),
-  //NATIVE_METHOD(Field, setSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V"),
-  //NATIVE_METHOD(Field, setZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V"),
+  NATIVE_METHOD(Field, getFieldModifiers, "(Ljava/lang/Class;I)I"),
+
+  NATIVE_METHOD(Field, getBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)B"),
+  NATIVE_METHOD(Field, getCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)C"),
+  NATIVE_METHOD(Field, getDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)D"),
+  NATIVE_METHOD(Field, getFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)F"),
+  NATIVE_METHOD(Field, getField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZ)Ljava/lang/Object;"),
+  NATIVE_METHOD(Field, getIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)I"),
+  NATIVE_METHOD(Field, getJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)J"),
+  NATIVE_METHOD(Field, getSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)S"),
+  NATIVE_METHOD(Field, getZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZC)Z"),
+  NATIVE_METHOD(Field, setBField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCB)V"),
+  NATIVE_METHOD(Field, setCField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCC)V"),
+  NATIVE_METHOD(Field, setDField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCD)V"),
+  NATIVE_METHOD(Field, setFField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCF)V"),
+  NATIVE_METHOD(Field, setField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZLjava/lang/Object;)V"),
+  NATIVE_METHOD(Field, setIField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCI)V"),
+  NATIVE_METHOD(Field, setJField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCJ)V"),
+  NATIVE_METHOD(Field, setSField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCS)V"),
+  NATIVE_METHOD(Field, setZField, "(Ljava/lang/Object;Ljava/lang/Class;Ljava/lang/Class;IZCZ)V"),
 };
 
 }  // namespace
 
 void register_java_lang_reflect_Field(JNIEnv* env) {
+  InitBoxingMethod(gBoolean_valueOf, "Ljava/lang/Boolean;", "(Z)Ljava/lang/Boolean;");
+  InitBoxingMethod(gByte_valueOf, "Ljava/lang/Byte;", "(B)Ljava/lang/Byte;");
+  InitBoxingMethod(gCharacter_valueOf, "Ljava/lang/Character;", "(C)Ljava/lang/Character;");
+  InitBoxingMethod(gDouble_valueOf, "Ljava/lang/Double;", "(D)Ljava/lang/Double;");
+  InitBoxingMethod(gFloat_valueOf, "Ljava/lang/Float;", "(F)Ljava/lang/Float;");
+  InitBoxingMethod(gInteger_valueOf, "Ljava/lang/Integer;", "(I)Ljava/lang/Integer;");
+  InitBoxingMethod(gLong_valueOf, "Ljava/lang/Long;", "(J)Ljava/lang/Long;");
+  InitBoxingMethod(gShort_valueOf, "Ljava/lang/Short;", "(S)Ljava/lang/Short;");
   jniRegisterNativeMethods(env, "java/lang/reflect/Field", gMethods, NELEM(gMethods));
 }