Make ResolveField not rely on Field::GetType resolution

Change-Id: I10f4a874809ac9db2cd54e200cf10eb7c8979fce
diff --git a/src/check_jni.cc b/src/check_jni.cc
index c740291..15cc161 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -237,12 +237,12 @@
     if (f == NULL) {
       return;
     }
-    Class* f_type = f->GetType();
     // check invariant that all jfieldIDs have resolved types
-    DCHECK(f_type != NULL);
+    DCHECK(f->GetType() != NULL);
     Class* c = o->GetClass();
-    if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f_type) == NULL) {
-      LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f) << " not valid for an object of class " << PrettyTypeOf(o);
+    if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f->GetTypeDescriptor()) == NULL) {
+      LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f) 
+                 << " not valid for an object of class " << PrettyTypeOf(o);
       JniAbort();
     }
   }
diff --git a/src/class_linker.cc b/src/class_linker.cc
index de35d33..afb6721 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -284,14 +284,14 @@
   SetClassRoot(kJavaLangString, java_lang_String.get());
 
   // Setup the primitive type classes.
-  SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Class::kPrimBoolean));
-  SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Class::kPrimByte));
-  SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Class::kPrimShort));
-  SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Class::kPrimInt));
-  SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Class::kPrimLong));
-  SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Class::kPrimFloat));
-  SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Class::kPrimDouble));
-  SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Class::kPrimVoid));
+  SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Primitive::kPrimBoolean));
+  SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Primitive::kPrimByte));
+  SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Primitive::kPrimShort));
+  SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Primitive::kPrimInt));
+  SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Primitive::kPrimLong));
+  SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Primitive::kPrimFloat));
+  SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Primitive::kPrimDouble));
+  SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Primitive::kPrimVoid));
 
   // Create array interface entries to populate once we can load system classes
   array_interfaces_ = AllocClassArray(2);
@@ -343,7 +343,7 @@
   // now we can use FindSystemClass
 
   // run char class through InitializePrimitiveClass to finish init
-  InitializePrimitiveClass(char_class.get(), "C", Class::kPrimChar);
+  InitializePrimitiveClass(char_class.get(), "C", Primitive::kPrimChar);
   SetClassRoot(kPrimitiveChar, char_class.get());  // needs descriptor
 
   // Object and String need to be rerun through FindSystemClass to finish init
@@ -875,7 +875,7 @@
 Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
   DCHECK_GE(class_size, sizeof(Class));
   SirtRef<Class> klass(Heap::AllocObject(java_lang_Class, class_size)->AsClass());
-  klass->SetPrimitiveType(Class::kPrimNot);  // default to not being primitive
+  klass->SetPrimitiveType(Primitive::kPrimNot);  // default to not being primitive
   klass->SetClassSize(class_size);
   return klass.get();
 }
@@ -1062,7 +1062,7 @@
       DexFile::Field dex_field;
       dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
       const DexFile::FieldId& field_id = dex_file.GetFieldId(dex_field.field_idx_);
-      const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+      const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
       char c = descriptor[0];
       if (c == 'L' || c == '[') {
         num_ref++;
@@ -1138,7 +1138,7 @@
   CHECK_EQ(access_flags & ~kAccJavaFlagsMask, 0U);
   klass->SetAccessFlags(access_flags);
   klass->SetClassLoader(class_loader);
-  DCHECK(klass->GetPrimitiveType() == Class::kPrimNot);
+  DCHECK(klass->GetPrimitiveType() == Primitive::kPrimNot);
   klass->SetStatus(Class::kStatusIdx);
 
   klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
@@ -1264,7 +1264,7 @@
 
   // In order to access primitive types using GetTypeDuringLinking we need to
   // ensure they are resolved into the dex cache
-  const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+  const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
   if (descriptor[1] == '\0') {
     // only the descriptors of primitive types should be 1 character long
     Class* resolved = ResolveType(dex_file, field_id.type_idx_, klass.get());
@@ -1430,7 +1430,7 @@
 
 Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class,
                                              const char* descriptor,
-                                             Class::PrimitiveType type) {
+                                             Primitive::Type type) {
   // TODO: deduce one argument from the other
   CHECK(primitive_class != NULL);
   primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
@@ -1532,7 +1532,7 @@
   Class* java_lang_Object = GetClassRoot(kJavaLangObject);
   new_class->SetSuperClass(java_lang_Object);
   new_class->SetVTable(java_lang_Object->GetVTable());
-  new_class->SetPrimitiveType(Class::kPrimNot);
+  new_class->SetPrimitiveType(Primitive::kPrimNot);
   new_class->SetClassLoader(component_type->GetClassLoader());
   new_class->SetStatus(Class::kStatusInitialized);
   // don't need to set new_class->SetObjectSize(..)
@@ -1582,25 +1582,27 @@
 }
 
 Class* ClassLinker::FindPrimitiveClass(char type) {
-  switch (type) {
-    case 'B':
+  switch (Primitive::GetType(type)) {
+    case Primitive::kPrimByte:
       return GetClassRoot(kPrimitiveByte);
-    case 'C':
+    case Primitive::kPrimChar:
       return GetClassRoot(kPrimitiveChar);
-    case 'D':
+    case Primitive::kPrimDouble:
       return GetClassRoot(kPrimitiveDouble);
-    case 'F':
+    case Primitive::kPrimFloat:
       return GetClassRoot(kPrimitiveFloat);
-    case 'I':
+    case Primitive::kPrimInt:
       return GetClassRoot(kPrimitiveInt);
-    case 'J':
+    case Primitive::kPrimLong:
       return GetClassRoot(kPrimitiveLong);
-    case 'S':
+    case Primitive::kPrimShort:
       return GetClassRoot(kPrimitiveShort);
-    case 'Z':
+    case Primitive::kPrimBoolean:
       return GetClassRoot(kPrimitiveBoolean);
-    case 'V':
+    case Primitive::kPrimVoid:
       return GetClassRoot(kPrimitiveVoid);
+    case Primitive::kPrimNot:
+      break;
   }
   std::string printable_type(PrintableChar(type));
   ThrowNoClassDefFoundError("Not a primitive type: %s", printable_type.c_str());
@@ -2419,12 +2421,12 @@
 struct LinkFieldsComparator {
   bool operator()(const Field* field1, const Field* field2) {
     // First come reference fields, then 64-bit, and finally 32-bit
-    const Class* type1 = field1->GetTypeDuringLinking();
-    const Class* type2 = field2->GetTypeDuringLinking();
-    bool isPrimitive1 = type1 != NULL && type1->IsPrimitive();
-    bool isPrimitive2 = type2 != NULL && type2->IsPrimitive();
-    bool is64bit1 = isPrimitive1 && (type1->IsPrimitiveLong() || type1->IsPrimitiveDouble());
-    bool is64bit2 = isPrimitive2 && (type2->IsPrimitiveLong() || type2->IsPrimitiveDouble());
+    Primitive::Type type1 = field1->GetPrimitiveType();
+    Primitive::Type type2 = field2->GetPrimitiveType();
+    bool isPrimitive1 = type1 != Primitive::kPrimNot;
+    bool isPrimitive2 = type2 != Primitive::kPrimNot;
+    bool is64bit1 = isPrimitive1 && (type1 == Primitive::kPrimLong || type1 == Primitive::kPrimDouble);
+    bool is64bit2 = isPrimitive2 && (type2 == Primitive::kPrimLong || type2 == Primitive::kPrimDouble);
     int order1 = (!isPrimitive1 ? 0 : (is64bit1 ? 1 : 2));
     int order2 = (!isPrimitive2 ? 0 : (is64bit2 ? 1 : 2));
     if (order1 != order2) {
@@ -2477,9 +2479,8 @@
   size_t num_reference_fields = 0;
   for (; current_field < num_fields; current_field++) {
     Field* field = grouped_and_sorted_fields.front();
-    const Class* type = field->GetTypeDuringLinking();
-    // if a field's type at this point is NULL it isn't primitive
-    bool isPrimitive = type != NULL && type->IsPrimitive();
+    Primitive::Type type = field->GetPrimitiveType();
+    bool isPrimitive = type != Primitive::kPrimNot;
     if (isPrimitive) {
       break; // past last reference, move on to the next phase
     }
@@ -2496,10 +2497,9 @@
   if (current_field != num_fields && !IsAligned<8>(field_offset.Uint32Value())) {
     for (size_t i = 0; i < grouped_and_sorted_fields.size(); i++) {
       Field* field = grouped_and_sorted_fields[i];
-      const Class* type = field->GetTypeDuringLinking();
-      CHECK(type != NULL);  // should only be working on primitive types
-      DCHECK(type->IsPrimitive());
-      if (type->IsPrimitiveLong() || type->IsPrimitiveDouble()) {
+      Primitive::Type type = field->GetPrimitiveType();
+      CHECK(type != Primitive::kPrimNot);  // should only be working on primitive types
+      if (type == Primitive::kPrimLong || type == Primitive::kPrimDouble) {
         continue;
       }
       fields->Set(current_field++, field);
@@ -2518,13 +2518,12 @@
   while (!grouped_and_sorted_fields.empty()) {
     Field* field = grouped_and_sorted_fields.front();
     grouped_and_sorted_fields.pop_front();
-    const Class* type = field->GetTypeDuringLinking();
-    CHECK(type != NULL);  // should only be working on primitive types
-    DCHECK(type->IsPrimitive());
+    Primitive::Type type = field->GetPrimitiveType();
+    CHECK(type != Primitive::kPrimNot);  // should only be working on primitive types
     fields->Set(current_field, field);
     field->SetOffset(field_offset);
     field_offset = MemberOffset(field_offset.Uint32Value() +
-                                ((type->IsPrimitiveLong() || type->IsPrimitiveDouble())
+                                ((type == Primitive::kPrimLong || type == Primitive::kPrimDouble)
                                  ? sizeof(uint64_t)
                                  : sizeof(uint32_t)));
     current_field++;
@@ -2551,8 +2550,8 @@
                 << " field=" << PrettyField(field)
                 << " offset=" << field->GetField32(MemberOffset(Field::OffsetOffset()), false);
     }
-    const Class* type = field->GetTypeDuringLinking();
-    bool is_primitive = (type != NULL && type->IsPrimitive());
+    Primitive::Type type = field->GetPrimitiveType();
+    bool is_primitive = type != Primitive::kPrimNot;
     if (klass->GetDescriptor()->Equals("Ljava/lang/ref/Reference;") && field->GetName()->Equals("referent")) {
       is_primitive = true; // We lied above, so we have to expect a lie here.
     }
@@ -2727,23 +2726,18 @@
     return NULL;
   }
 
-  const char* name = dex_file.dexStringById(field_id.name_idx_);
-  Class* field_type = ResolveType(dex_file, field_id.type_idx_, dex_cache, class_loader);
-  if (field_type == NULL) {
-    // TODO: LinkageError?
-    UNIMPLEMENTED(WARNING) << "Failed to resolve type of field " << name
-                           << " in " << PrettyClass(klass);
-    return NULL;
-}
+  const char* name = dex_file.GetFieldName(field_id);
+  const char* type = dex_file.GetFieldTypeDescriptor(field_id);
   if (is_static) {
-    resolved = klass->FindStaticField(name, field_type);
+    resolved = klass->FindStaticField(name, type);
   } else {
-    resolved = klass->FindInstanceField(name, field_type);
+    resolved = klass->FindInstanceField(name, type);
   }
   if (resolved != NULL) {
     dex_cache->SetResolvedField(field_idx, resolved);
   } else {
-    DCHECK(Thread::Current()->IsExceptionPending());
+    DCHECK(Thread::Current()->IsExceptionPending())
+        << PrettyClass(klass) << " " << name << " " << type << " " << is_static;
   }
   return resolved;
 }
diff --git a/src/class_linker.h b/src/class_linker.h
index dd78174..e2c5921 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -265,13 +265,12 @@
   CodeAndDirectMethods* AllocCodeAndDirectMethods(size_t length);
   InterfaceEntry* AllocInterfaceEntry(Class* interface);
 
-  Class* CreatePrimitiveClass(const char* descriptor,
-                              Class::PrimitiveType type) {
+  Class* CreatePrimitiveClass(const char* descriptor, Primitive::Type type) {
     return InitializePrimitiveClass(AllocClass(sizeof(Class)), descriptor, type);
   }
   Class* InitializePrimitiveClass(Class* primitive_class,
                                   const char* descriptor,
-                                  Class::PrimitiveType type);
+                                  Primitive::Type type);
 
 
   Class* CreateArrayClass(const std::string& descriptor,
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 1b43825..54da19f 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -235,6 +235,7 @@
     EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
     for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) {
       Field* field = klass->GetInstanceField(i);
+      ASSERT_TRUE(!field->IsPrimitiveType());
       Class* field_type = field->GetType();
       ASSERT_TRUE(field_type != NULL);
       ASSERT_TRUE(!field_type->IsPrimitive());
@@ -243,7 +244,7 @@
       Field* field = klass->GetInstanceField(i);
       Class* field_type = field->GetType();
       ASSERT_TRUE(field_type != NULL);
-      if (!field_type->IsPrimitive()) {
+      if (!field->IsPrimitiveType() || !field_type->IsPrimitive()) {
         // While Reference.referent is not primitive, the ClassLinker
         // treats it as such so that the garbage collector won't scan it.
         EXPECT_EQ(PrettyField(field), "java.lang.Object java.lang.ref.Reference.referent");
@@ -830,49 +831,49 @@
 
   EXPECT_EQ(9U, statics->NumStaticFields());
 
-  Field* s0 = statics->FindStaticField("s0", class_linker_->FindClass("Z", class_loader.get()));
+  Field* s0 = statics->FindStaticField("s0", "Z");
   EXPECT_TRUE(s0->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Field;"));
-  EXPECT_TRUE(s0->GetType()->IsPrimitiveBoolean());
+  EXPECT_TRUE(s0->GetPrimitiveType() == Primitive::kPrimBoolean);
   EXPECT_EQ(true, s0->GetBoolean(NULL));
   s0->SetBoolean(NULL, false);
 
-  Field* s1 = statics->FindStaticField("s1", class_linker_->FindClass("B", class_loader.get()));
-  EXPECT_TRUE(s1->GetType()->IsPrimitiveByte());
+  Field* s1 = statics->FindStaticField("s1", "B");
+  EXPECT_TRUE(s1->GetPrimitiveType() == Primitive::kPrimByte);
   EXPECT_EQ(5, s1->GetByte(NULL));
   s1->SetByte(NULL, 6);
 
-  Field* s2 = statics->FindStaticField("s2", class_linker_->FindClass("C", class_loader.get()));
-  EXPECT_TRUE(s2->GetType()->IsPrimitiveChar());
+  Field* s2 = statics->FindStaticField("s2", "C");
+  EXPECT_TRUE(s2->GetPrimitiveType() == Primitive::kPrimChar);
   EXPECT_EQ('a', s2->GetChar(NULL));
   s2->SetChar(NULL, 'b');
 
-  Field* s3 = statics->FindStaticField("s3", class_linker_->FindClass("S", class_loader.get()));
-  EXPECT_TRUE(s3->GetType()->IsPrimitiveShort());
+  Field* s3 = statics->FindStaticField("s3", "S");
+  EXPECT_TRUE(s3->GetPrimitiveType() == Primitive::kPrimShort);
   EXPECT_EQ(-536, s3->GetShort(NULL));
   s3->SetShort(NULL, -535);
 
-  Field* s4 = statics->FindStaticField("s4", class_linker_->FindClass("I", class_loader.get()));
-  EXPECT_TRUE(s4->GetType()->IsPrimitiveInt());
+  Field* s4 = statics->FindStaticField("s4", "I");
+  EXPECT_TRUE(s4->GetPrimitiveType() == Primitive::kPrimInt);
   EXPECT_EQ(2000000000, s4->GetInt(NULL));
   s4->SetInt(NULL, 2000000001);
 
-  Field* s5 = statics->FindStaticField("s5", class_linker_->FindClass("J", class_loader.get()));
-  EXPECT_TRUE(s5->GetType()->IsPrimitiveLong());
+  Field* s5 = statics->FindStaticField("s5", "J");
+  EXPECT_TRUE(s5->GetPrimitiveType() == Primitive::kPrimLong);
   EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(NULL));
   s5->SetLong(NULL, 0x34567890abcdef12LL);
 
-  Field* s6 = statics->FindStaticField("s6", class_linker_->FindClass("F", class_loader.get()));
-  EXPECT_TRUE(s6->GetType()->IsPrimitiveFloat());
+  Field* s6 = statics->FindStaticField("s6", "F");
+  EXPECT_TRUE(s6->GetPrimitiveType() == Primitive::kPrimFloat);
   EXPECT_EQ(0.5, s6->GetFloat(NULL));
   s6->SetFloat(NULL, 0.75);
 
-  Field* s7 = statics->FindStaticField("s7", class_linker_->FindClass("D", class_loader.get()));
-  EXPECT_TRUE(s7->GetType()->IsPrimitiveDouble());
+  Field* s7 = statics->FindStaticField("s7", "D");
+  EXPECT_TRUE(s7->GetPrimitiveType() == Primitive::kPrimDouble);
   EXPECT_EQ(16777217, s7->GetDouble(NULL));
   s7->SetDouble(NULL, 16777219);
 
-  Field* s8 = statics->FindStaticField("s8", class_linker_->FindClass("Ljava/lang/String;", class_loader.get()));
-  EXPECT_FALSE(s8->GetType()->IsPrimitive());
+  Field* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
+  EXPECT_TRUE(s8->GetPrimitiveType() == Primitive::kPrimNot);
   EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android"));
   s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot"));
 
diff --git a/src/common_test.h b/src/common_test.h
index 3f56aab..928cb51 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -288,7 +288,7 @@
                                            const StringPiece& field_name) {
     for (size_t i = 0; i < dex_file.NumFieldIds(); i++) {
       const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
-      if (class_descriptor == dex_file.GetFieldClassDescriptor(field_id)
+      if (class_descriptor == dex_file.GetFieldDeclaringClassDescriptor(field_id)
           && field_name == dex_file.GetFieldName(field_id)) {
         return i;
       }
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index 35da6f2..d1b377a 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -91,18 +91,18 @@
   for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
     Method* method = dex_cache->GetResolvedMethod(i);
     EXPECT_TRUE(method != NULL) << "method_idx=" << i
-                                << " " << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+                                << " " << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
                                 << " " << dex->GetMethodName(dex->GetMethodId(i));
     EXPECT_TRUE(method->GetCode() != NULL) << "method_idx=" << i
                                            << " "
-                                           << dex->GetMethodClassDescriptor(dex->GetMethodId(i))
+                                           << dex->GetMethodDeclaringClassDescriptor(dex->GetMethodId(i))
                                            << " " << dex->GetMethodName(dex->GetMethodId(i));
   }
   EXPECT_EQ(dex->NumFieldIds(), dex_cache->NumResolvedFields());
   for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
     Field* field = dex_cache->GetResolvedField(i);
     EXPECT_TRUE(field != NULL) << "field_idx=" << i
-                               << " " << dex->GetFieldClassDescriptor(dex->GetFieldId(i))
+                               << " " << dex->GetFieldDeclaringClassDescriptor(dex->GetFieldId(i))
                                << " " << dex->GetFieldName(dex->GetFieldId(i));
   }
 
diff --git a/src/dex_file.h b/src/dex_file.h
index c30c5ca..3acd79f 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -425,19 +425,25 @@
     return dexStringById(type_id.descriptor_idx_);
   }
 
-  // Returns the class descriptor string of a field id.
-  const char* GetFieldClassDescriptor(const FieldId& field_id) const {
+  // Returns the declaring class descriptor string of a field id.
+  const char* GetFieldDeclaringClassDescriptor(const FieldId& field_id) const {
     const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_);
     return GetTypeDescriptor(type_id);
   }
 
+  // Returns the class descriptor string of a field id.
+  const char* GetFieldTypeDescriptor(const FieldId& field_id) const {
+    const DexFile::TypeId& type_id = GetTypeId(field_id.type_idx_);
+    return GetTypeDescriptor(type_id);
+  }
+
   // Returns the name of a field id.
   const char* GetFieldName(const FieldId& field_id) const {
     return dexStringById(field_id.name_idx_);
   }
 
-  // Returns the class descriptor string of a method id.
-  const char* GetMethodClassDescriptor(const MethodId& method_id) const {
+  // Returns the declaring class descriptor string of a method id.
+  const char* GetMethodDeclaringClassDescriptor(const MethodId& method_id) const {
     const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_);
     return GetTypeDescriptor(type_id);
   }
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index da7f63f..e4d9f84 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -289,18 +289,18 @@
   }
 }
 
-static RegType::Type RegTypeFromPrimitiveType(Class::PrimitiveType prim_type) {
+static RegType::Type RegTypeFromPrimitiveType(Primitive::Type prim_type) {
   switch (prim_type) {
-    case Class::kPrimBoolean: return RegType::kRegTypeBoolean;
-    case Class::kPrimByte:    return RegType::kRegTypeByte;
-    case Class::kPrimShort:   return RegType::kRegTypeShort;
-    case Class::kPrimChar:    return RegType::kRegTypeChar;
-    case Class::kPrimInt:     return RegType::kRegTypeInteger;
-    case Class::kPrimLong:    return RegType::kRegTypeLongLo;
-    case Class::kPrimFloat:   return RegType::kRegTypeFloat;
-    case Class::kPrimDouble:  return RegType::kRegTypeDoubleLo;
-    case Class::kPrimVoid:
-    default:                  return RegType::kRegTypeUnknown;
+    case Primitive::kPrimBoolean: return RegType::kRegTypeBoolean;
+    case Primitive::kPrimByte:    return RegType::kRegTypeByte;
+    case Primitive::kPrimShort:   return RegType::kRegTypeShort;
+    case Primitive::kPrimChar:    return RegType::kRegTypeChar;
+    case Primitive::kPrimInt:     return RegType::kRegTypeInteger;
+    case Primitive::kPrimLong:    return RegType::kRegTypeLongLo;
+    case Primitive::kPrimFloat:   return RegType::kRegTypeFloat;
+    case Primitive::kPrimDouble:  return RegType::kRegTypeDoubleLo;
+    case Primitive::kPrimVoid:
+    default:                      return RegType::kRegTypeUnknown;
   }
 }
 
@@ -2134,7 +2134,7 @@
             if (array_data[0] != Instruction::kArrayDataSignature) {
               Fail(VERIFY_ERROR_GENERIC) << "invalid magic for array-data";
             } else {
-              size_t elem_width = component_type->PrimitiveSize();
+              size_t elem_width = Primitive::ComponentSize(component_type->GetPrimitiveType());
               // Since we don't compress the data in Dex, expect to see equal width of data stored
               // in the table and expected from the array class.
               if (array_data[1] != elem_width) {
@@ -2952,7 +2952,7 @@
       DCHECK(failure_ != VERIFY_ERROR_NONE);
       return NULL;
     }
-    const char* name = dex_file_->dexStringById(method_id.name_idx_);
+    const char* name = dex_file_->GetMethodName(method_id);
     std::string signature(dex_file_->CreateMethodDescriptor(method_id.proto_idx_, NULL));
     if (is_direct) {
       res_method = klass->FindDirectMethod(name, signature);
@@ -2989,7 +2989,7 @@
     const DexFile::MethodId& method_id = dex_file_->GetMethodId(dec_insn.vB_);
     const char* method_name = dex_file_->GetMethodName(method_id);
     std::string method_signature = dex_file_->GetMethodSignature(method_id);
-    const char* class_descriptor = dex_file_->GetMethodClassDescriptor(method_id);
+    const char* class_descriptor = dex_file_->GetMethodDeclaringClassDescriptor(method_id);
     Fail(VERIFY_ERROR_GENERIC) << "unable to resolve method " << dec_insn.vB_ << ": "
                                << class_descriptor << "." << method_name << " " << method_signature;
     return NULL;
@@ -3236,7 +3236,7 @@
     const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
     Fail(VERIFY_ERROR_NO_FIELD) << "unable to resolve static field " << field_idx << " ("
                                 << dex_file_->GetFieldName(field_id) << ") in "
-                                << dex_file_->GetFieldClassDescriptor(field_id);
+                                << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
     DCHECK(Thread::Current()->IsExceptionPending());
     Thread::Current()->ClearException();
     return NULL;
@@ -3357,7 +3357,7 @@
     const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
     Fail(VERIFY_ERROR_NO_FIELD) << "unable to resolve instance field " << field_idx << " ("
                                 << dex_file_->GetFieldName(field_id) << ") in "
-                                << dex_file_->GetFieldClassDescriptor(field_id);
+                                << dex_file_->GetFieldDeclaringClassDescriptor(field_id);
     DCHECK(Thread::Current()->IsExceptionPending());
     Thread::Current()->ClearException();
     return NULL;
diff --git a/src/dex_verifier.h b/src/dex_verifier.h
index 3a614d5..0d86eb5 100644
--- a/src/dex_verifier.h
+++ b/src/dex_verifier.h
@@ -35,7 +35,7 @@
 
 /*
  * RegType holds information about the type of data held in a register. For most types it's a simple
- * enum. For reference types it holds a pointer to the ClassObject, and for uninitialized references
+ * enum. For reference types it holds a pointer to the Class*, and for uninitialized references
  * it holds an index into the UninitInstanceMap.
  */
 class RegType {
diff --git a/src/heap.cc b/src/heap.cc
index 01ba840..bd6d009 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -16,6 +16,10 @@
 
 namespace art {
 
+bool Heap::is_verbose_heap_ = false;
+
+bool Heap::is_verbose_gc_ = false;
+
 std::vector<Space*> Heap::spaces_;
 
 Space* Heap::alloc_space_ = NULL;
@@ -58,10 +62,14 @@
   }
 };
 
-void Heap::Init(size_t initial_size, size_t maximum_size,
+void Heap::Init(bool is_verbose_heap, bool is_verbose_gc,
+                size_t initial_size, size_t maximum_size,
                 const std::vector<std::string>& image_file_names) {
+  is_verbose_heap_ = is_verbose_heap;
+  is_verbose_gc_ = is_verbose_gc;
+
   const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
+  if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
     LOG(INFO) << "Heap::Init entering";
   }
 
@@ -132,7 +140,7 @@
   // make it clear that you can't use locks during heap initialization.
   lock_ = new Mutex("Heap lock");
 
-  if (runtime->IsVerboseStartup()) {
+  if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
     LOG(INFO) << "Heap::Init exiting";
   }
 }
@@ -283,7 +291,7 @@
 
 void Heap::RecordImageAllocations(Space* space) {
   const Runtime* runtime = Runtime::Current();
-  if (runtime->IsVerboseStartup()) {
+  if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
     LOG(INFO) << "Heap::RecordImageAllocations entering";
   }
   DCHECK(!Runtime::Current()->IsStarted());
@@ -296,7 +304,7 @@
     live_bitmap_->Set(obj);
     current += RoundUp(obj->SizeOf(), kObjectAlignment);
   }
-  if (runtime->IsVerboseStartup()) {
+  if (is_verbose_heap_ || runtime->IsVerboseStartup()) {
     LOG(INFO) << "Heap::RecordImageAllocations exiting";
   }
 }
@@ -344,14 +352,12 @@
     ++Runtime::Current()->GetStats()->gc_for_alloc_count;
     ++Thread::Current()->GetStats()->gc_for_alloc_count;
   }
-  LOG(INFO) << "GC_FOR_ALLOC: AllocWithoutGrowth: TODO: test";
   CollectGarbageInternal();
   ptr = space->AllocWithoutGrowth(size);
   if (ptr != NULL) {
     return ptr;
   }
 
-  LOG(INFO) << "GC_FOR_ALLOC: AllocWithGrowth: TODO: test";
   // Even that didn't work;  this is an exceptional state.
   // Try harder, growing the heap if necessary.
   ptr = space->AllocWithGrowth(size);
@@ -361,8 +367,10 @@
     // OLD-TODO: may want to grow a little bit more so that the amount of
     //       free space is equal to the old free space + the
     //       utilization slop for the new allocation.
-    LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
-              << "for " << size << "-byte allocation";
+    if (is_verbose_gc_) {
+      LOG(INFO) << "Grow heap (frag case) to " << new_footprint / MB
+                << "for " << size << "-byte allocation";
+    }
     return ptr;
   }
 
@@ -373,8 +381,10 @@
   // cleared before throwing an OOME.
 
   // OLD-TODO: wait for the finalizers from the previous GC to finish
-  LOG(INFO) << "Forcing collection of SoftReferences for "
-            << size << "-byte allocation";
+  if (is_verbose_gc_) {
+    LOG(INFO) << "Forcing collection of SoftReferences for "
+              << size << "-byte allocation";
+  }
   CollectGarbageInternal();
   ptr = space->AllocWithGrowth(size);
   if (ptr != NULL) {
@@ -512,11 +522,15 @@
   size_t percentFree = 100 - static_cast<size_t>(100.0f * float(num_bytes_allocated_) / footprint);
 
   uint32_t duration = (t1 - t0)/1000/1000;
-  LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, "
-            << percentFree << "% free "
-            << (num_bytes_allocated_/1024) << "KiB/" << (footprint/1024) << "KiB, "
-            << "paused " << duration << "ms";
-  timings.Dump();
+  if (is_verbose_gc_) {
+    LOG(INFO) << "GC freed " << (is_small ? "<" : "") << kib_freed << "KiB, "
+              << percentFree << "% free "
+              << (num_bytes_allocated_/1024) << "KiB/" << (footprint/1024) << "KiB, "
+              << "paused " << duration << "ms";
+  }
+  if (is_verbose_heap_) {
+    timings.Dump();
+  }
 }
 
 void Heap::WaitForConcurrentGcToComplete() {
@@ -547,8 +561,10 @@
 void Heap::SetIdealFootprint(size_t max_allowed_footprint)
 {
   if (max_allowed_footprint > Heap::maximum_size_) {
-    LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
-              << " to " << Heap::maximum_size_;
+    if (is_verbose_gc_) {
+      LOG(INFO) << "Clamp target GC heap from " << max_allowed_footprint
+                << " to " << Heap::maximum_size_;
+    }
     max_allowed_footprint = Heap::maximum_size_;
   }
 
diff --git a/src/heap.h b/src/heap.h
index 433bf6a..9e21272 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -45,11 +45,20 @@
   // Create a heap with the requested sizes. The possible empty
   // image_file_names names specify Spaces to load based on
   // ImageWriter output.
-  static void Init(size_t starting_size, size_t maximum_size,
+  static void Init(bool is_verbose_heap, bool is_verbose_gc,
+                   size_t starting_size, size_t maximum_size,
                    const std::vector<std::string>& image_file_names);
 
   static void Destroy();
 
+  static bool IsVerboseHeap() {
+    return is_verbose_heap_;
+  }
+
+  static bool IsVerboseGc() {
+    return is_verbose_gc_;
+  }
+
   // Allocates and initializes storage for an object instance.
   static Object* AllocObject(Class* klass, size_t num_bytes);
 
@@ -187,6 +196,10 @@
 
   static Mutex* lock_;
 
+  static bool is_verbose_heap_;
+
+  static bool is_verbose_gc_;
+
   static std::vector<Space*> spaces_;
 
   // default Space for allocations
diff --git a/src/java_lang_reflect_Field.cc b/src/java_lang_reflect_Field.cc
index 7d43b2e..a2f09e7 100644
--- a/src/java_lang_reflect_Field.cc
+++ b/src/java_lang_reflect_Field.cc
@@ -30,39 +30,39 @@
 }
 
 bool GetFieldValue(Object* o, Field* f, JValue& value, bool allow_references) {
-  switch (f->GetType()->GetPrimitiveType()) {
-  case Class::kPrimBoolean:
+  switch (f->GetPrimitiveType()) {
+  case Primitive::kPrimBoolean:
     value.z = f->GetBoolean(o);
     return true;
-  case Class::kPrimByte:
+  case Primitive::kPrimByte:
     value.b = f->GetByte(o);
     return true;
-  case Class::kPrimChar:
+  case Primitive::kPrimChar:
     value.c = f->GetChar(o);
     return true;
-  case Class::kPrimDouble:
+  case Primitive::kPrimDouble:
     value.d = f->GetDouble(o);
     return true;
-  case Class::kPrimFloat:
+  case Primitive::kPrimFloat:
     value.f = f->GetFloat(o);
     return true;
-  case Class::kPrimInt:
+  case Primitive::kPrimInt:
     value.i = f->GetInt(o);
     return true;
-  case Class::kPrimLong:
+  case Primitive::kPrimLong:
     value.j = f->GetLong(o);
     return true;
-  case Class::kPrimShort:
+  case Primitive::kPrimShort:
     value.s = f->GetShort(o);
     return true;
-  case Class::kPrimNot:
+  case Primitive::kPrimNot:
     if (allow_references) {
       value.l = f->GetObject(o);
       return true;
     }
     // Else break to report an error.
     break;
-  case Class::kPrimVoid:
+  case Primitive::kPrimVoid:
     // Never okay.
     break;
   }
@@ -101,7 +101,8 @@
   // Widen it if necessary (and possible).
   JValue wide_value;
   Class* dst_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor);
-  if (!ConvertPrimitiveValue(f->GetType(), dst_type, field_value, wide_value)) {
+  if (!ConvertPrimitiveValue(f->GetPrimitiveType(), dst_type->GetPrimitiveType(),
+                             field_value, wide_value)) {
     return JValue();
   }
   return wide_value;
@@ -140,38 +141,38 @@
 }
 
 void SetFieldValue(Object* o, Field* f, const JValue& new_value, bool allow_references) {
-  switch (f->GetType()->GetPrimitiveType()) {
-  case Class::kPrimBoolean:
+  switch (f->GetPrimitiveType()) {
+  case Primitive::kPrimBoolean:
     f->SetBoolean(o, new_value.z);
     break;
-  case Class::kPrimByte:
+  case Primitive::kPrimByte:
     f->SetByte(o, new_value.b);
     break;
-  case Class::kPrimChar:
+  case Primitive::kPrimChar:
     f->SetChar(o, new_value.c);
     break;
-  case Class::kPrimDouble:
+  case Primitive::kPrimDouble:
     f->SetDouble(o, new_value.d);
     break;
-  case Class::kPrimFloat:
+  case Primitive::kPrimFloat:
     f->SetFloat(o, new_value.f);
     break;
-  case Class::kPrimInt:
+  case Primitive::kPrimInt:
     f->SetInt(o, new_value.i);
     break;
-  case Class::kPrimLong:
+  case Primitive::kPrimLong:
     f->SetLong(o, new_value.j);
     break;
-  case Class::kPrimShort:
+  case Primitive::kPrimShort:
     f->SetShort(o, new_value.s);
     break;
-  case Class::kPrimNot:
+  case Primitive::kPrimNot:
     if (allow_references) {
       f->SetObject(o, new_value.l);
       break;
     }
     // Else fall through to report an error.
-  case Class::kPrimVoid:
+  case Primitive::kPrimVoid:
     // Never okay.
     Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
         "Not a primitive field: %s", PrettyField(f).c_str());
@@ -195,7 +196,8 @@
   // Widen the value if necessary (and possible).
   JValue wide_value;
   Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor);
-  if (!ConvertPrimitiveValue(src_type, f->GetType(), new_value, wide_value)) {
+  if (!ConvertPrimitiveValue(src_type->GetPrimitiveType(), f->GetPrimitiveType(),
+                             new_value, wide_value)) {
     return;
   }
 
@@ -282,7 +284,7 @@
   if (!GetFieldValue(o, f, value, true)) {
     return NULL;
   }
-  BoxPrimitive(env, f->GetType(), value);
+  BoxPrimitive(env, f->GetPrimitiveType(), value);
 
   return AddLocalReference<jobject>(env, value.l);
 }
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 0ece455..0982f83 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -336,10 +336,11 @@
         "\"%s\" or its superclasses", sig, name, class_descriptor.c_str());
     return NULL;
   }
+  std::string field_type_descriptor = field_type->GetDescriptor()->ToModifiedUtf8();
   if (is_static) {
-    field = c->FindStaticField(name, field_type);
+    field = c->FindStaticField(name, field_type_descriptor);
   } else {
-    field = c->FindInstanceField(name, field_type);
+    field = c->FindInstanceField(name, field_type_descriptor);
   }
   if (field == NULL) {
     std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index d70d10d..4cc6b22 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -110,7 +110,9 @@
   finger_ = reinterpret_cast<Object*>(~0);
   ProcessMarkStack();
   timings.AddSplit("ProcessMarkStack");
-  timings.Dump();
+  if (Heap::IsVerboseHeap()) {
+    timings.Dump();
+  }
 }
 
 void MarkSweep::ReMarkRoots() {
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 73b92a0..02aecfc 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -328,9 +328,6 @@
       StringAppendF(&summary, "METHOD %s", PrettyMethod(method).c_str());
     } else if (obj->IsField()) {
       Field* field = obj->AsField();
-      Class* type = field->GetType();
-      std::string type_string;
-      type_string += (type == NULL) ? "<UNKNOWN>" : type->GetDescriptor()->ToModifiedUtf8();
       StringAppendF(&summary, "FIELD %s", PrettyField(field).c_str());
     } else if (obj->IsArrayInstance()) {
       StringAppendF(&summary, "ARRAY %d", obj->AsArray()->GetLength());
diff --git a/src/object.cc b/src/object.cc
index ab95885..91328aa 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -102,6 +102,31 @@
   return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
 }
 
+bool Field::IsPrimitiveType() const {
+  Class* type = GetTypeDuringLinking();
+  return (type == NULL || type->IsPrimitive());
+}
+
+Primitive::Type Field::GetPrimitiveType() const {
+  Class* type = GetTypeDuringLinking();
+  if (type == NULL) {
+    return Primitive::kPrimNot;
+  }
+  return type->GetPrimitiveType();
+}
+
+size_t Field::PrimitiveSize() const {
+  return Primitive::FieldSize(GetPrimitiveType());
+}
+
+const char* Field::GetTypeDescriptor() const {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const DexFile& dex_file = class_linker->FindDexFile(GetDeclaringClass()->GetDexCache());
+  const char* descriptor = dex_file.dexStringByTypeIdx(GetTypeIdx());
+  DCHECK(descriptor != NULL);
+  return descriptor;
+}
+
 Class* Field::GetType() const {
   if (type_ == NULL) {
     type_ = Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
@@ -120,11 +145,11 @@
 }
 
 void Field::InitJavaFieldsLocked() {
-  GetType(); // Sets type_ as a side-effect. May throw.
+  GetType(); // Resolves type as a side-effect. May throw.
 }
 
 uint32_t Field::Get32(const Object* object) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -132,7 +157,7 @@
 }
 
 void Field::Set32(Object* object, uint32_t new_value) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -140,7 +165,7 @@
 }
 
 uint64_t Field::Get64(const Object* object) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -148,7 +173,7 @@
 }
 
 void Field::Set64(Object* object, uint64_t new_value) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -156,7 +181,7 @@
 }
 
 Object* Field::GetObj(const Object* object) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -164,7 +189,7 @@
 }
 
 void Field::SetObj(Object* object, const Object* new_value) const {
-  CHECK((object == NULL) == IsStatic());
+  CHECK((object == NULL) == IsStatic()) << PrettyField(this);
   if (IsStatic()) {
     object = declaring_class_;
   }
@@ -172,100 +197,100 @@
 }
 
 bool Field::GetBoolean(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveBoolean());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetBoolean(Object* object, bool z) const {
-  DCHECK(GetType()->IsPrimitiveBoolean());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimBoolean) << PrettyField(this);
   Set32(object, z);
 }
 
 int8_t Field::GetByte(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveByte());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetByte(Object* object, int8_t b) const {
-  DCHECK(GetType()->IsPrimitiveByte());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimByte) << PrettyField(this);
   Set32(object, b);
 }
 
 uint16_t Field::GetChar(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveChar());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetChar(Object* object, uint16_t c) const {
-  DCHECK(GetType()->IsPrimitiveChar());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimChar) << PrettyField(this);
   Set32(object, c);
 }
 
 int16_t Field::GetShort(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveShort());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetShort(Object* object, int16_t s) const {
-  DCHECK(GetType()->IsPrimitiveShort());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimShort) << PrettyField(this);
   Set32(object, s);
 }
 
 int32_t Field::GetInt(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveInt());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
   return Get32(object);
 }
 
 void Field::SetInt(Object* object, int32_t i) const {
-  DCHECK(GetType()->IsPrimitiveInt()) << PrettyField(this);
+  DCHECK(GetPrimitiveType() == Primitive::kPrimInt) << PrettyField(this);
   Set32(object, i);
 }
 
 int64_t Field::GetLong(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveLong());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
   return Get64(object);
 }
 
 void Field::SetLong(Object* object, int64_t j) const {
-  DCHECK(GetType()->IsPrimitiveLong());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimLong) << PrettyField(this);
   Set64(object, j);
 }
 
 float Field::GetFloat(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveFloat());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
   JValue float_bits;
   float_bits.i = Get32(object);
   return float_bits.f;
 }
 
 void Field::SetFloat(Object* object, float f) const {
-  DCHECK(GetType()->IsPrimitiveFloat());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimFloat) << PrettyField(this);
   JValue float_bits;
   float_bits.f = f;
   Set32(object, float_bits.i);
 }
 
 double Field::GetDouble(const Object* object) const {
-  DCHECK(GetType()->IsPrimitiveDouble());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
   JValue double_bits;
   double_bits.j = Get64(object);
   return double_bits.d;
 }
 
 void Field::SetDouble(Object* object, double d) const {
-  DCHECK(GetType()->IsPrimitiveDouble());
+  DCHECK(GetPrimitiveType() == Primitive::kPrimDouble) << PrettyField(this);
   JValue double_bits;
   double_bits.d = d;
   Set64(object, double_bits.j);
 }
 
 Object* Field::GetObject(const Object* object) const {
-  CHECK(!GetType()->IsPrimitive());
+  CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
   return GetObj(object);
 }
 
 void Field::SetObject(Object* object, const Object* l) const {
-  CHECK(!GetType()->IsPrimitive());
+  CHECK(GetPrimitiveType() == Primitive::kPrimNot) << PrettyField(this);
   SetObj(object, l);
 }
 
@@ -828,44 +853,6 @@
              new_reference_offsets, false);
 }
 
-size_t Class::PrimitiveSize() const {
-  switch (GetPrimitiveType()) {
-    case kPrimBoolean:
-    case kPrimByte:    return 1;
-    case kPrimChar:
-    case kPrimShort:   return 2;
-    case kPrimInt:
-    case kPrimFloat:   return 4;
-    case kPrimLong:
-    case kPrimDouble:  return 8;
-    default:
-      LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
-      return 0;
-  }
-}
-
-size_t Class::PrimitiveFieldSize() const {
-  return PrimitiveSize() <= 4 ? 4 : 8;
-}
-
-size_t Class::GetTypeSize(const String* descriptor) {
-  switch (descriptor->CharAt(0)) {
-  case 'B': return 1;  // byte
-  case 'C': return 2;  // char
-  case 'D': return 8;  // double
-  case 'F': return 4;  // float
-  case 'I': return 4;  // int
-  case 'J': return 8;  // long
-  case 'S': return 2;  // short
-  case 'Z': return 1;  // boolean
-  case 'L': return sizeof(Object*);
-  case '[': return sizeof(Array*);
-  default:
-    LOG(ERROR) << "Unknown type " << descriptor;
-    return 0;
-  }
-}
-
 bool Class::Implements(const Class* klass) const {
   DCHECK(klass != NULL);
   DCHECK(klass->IsInterface()) << PrettyClass(this);
@@ -1089,9 +1076,6 @@
     Method* method = GetVirtualMethod(i);
     if (method->GetName() == name && method->GetSignature() == signature) {
       return method;
-    } else {
-      LOG(INFO) << "Find (" << name->ToModifiedUtf8() << ", " << signature->ToModifiedUtf8()
-          << ") != " << PrettyMethod(method);
     }
   }
   return NULL;
@@ -1117,19 +1101,32 @@
   return NULL;
 }
 
-Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type) {
   // Is the field in this class?
   // Interfaces are not relevant because they can't contain instance fields.
   for (size_t i = 0; i < NumInstanceFields(); ++i) {
     Field* f = GetInstanceField(i);
-    if (f->GetName()->Equals(name) && type == f->GetType()) {
+    if (f->GetName()->Equals(name) &&
+        StringPiece(f->GetTypeDescriptor()) == type) {
       return f;
     }
   }
   return NULL;
 }
 
-Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredInstanceField(String* name, String* type) {
+  // Is the field in this class?
+  // Interfaces are not relevant because they can't contain instance fields.
+  for (size_t i = 0; i < NumInstanceFields(); ++i) {
+    Field* f = GetInstanceField(i);
+    if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& type) {
   // Is the field in this class, or any of its superclasses?
   // Interfaces are not relevant because they can't contain instance fields.
   for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
@@ -1141,18 +1138,64 @@
   return NULL;
 }
 
-Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
-  DCHECK(type != NULL);
-  for (size_t i = 0; i < NumStaticFields(); ++i) {
-    Field* f = GetStaticField(i);
-    if (f->GetName()->Equals(name) && f->GetType() == type) {
+Field* Class::FindInstanceField(String* name, String* type) {
+  // Is the field in this class, or any of its superclasses?
+  // Interfaces are not relevant because they can't contain instance fields.
+  for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
+    Field* f = c->FindDeclaredInstanceField(name, type);
+    if (f != NULL) {
       return f;
     }
   }
   return NULL;
 }
 
-Field* Class::FindStaticField(const StringPiece& name, Class* type) {
+Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& type) {
+  DCHECK(type != NULL);
+  for (size_t i = 0; i < NumStaticFields(); ++i) {
+    Field* f = GetStaticField(i);
+    if (f->GetName()->Equals(name) && StringPiece(f->GetTypeDescriptor()) == type) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindDeclaredStaticField(String* name, String* type) {
+  DCHECK(type != NULL);
+  for (size_t i = 0; i < NumStaticFields(); ++i) {
+    Field* f = GetStaticField(i);
+    if (f->GetName() == name && type->Equals(f->GetTypeDescriptor())) {
+      return f;
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindStaticField(const StringPiece& name, const StringPiece& type) {
+  // Is the field in this class (or its interfaces), or any of its
+  // superclasses (or their interfaces)?
+  for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
+    // Is the field in this class?
+    Field* f = c->FindDeclaredStaticField(name, type);
+    if (f != NULL) {
+      return f;
+    }
+
+    // Is this field in any of this class' interfaces?
+    for (int32_t i = 0; i < c->GetIfTableCount(); ++i) {
+      InterfaceEntry* interface_entry = c->GetIfTable()->Get(i);
+      Class* interface = interface_entry->GetInterface();
+      f = interface->FindDeclaredStaticField(name, type);
+      if (f != NULL) {
+        return f;
+      }
+    }
+  }
+  return NULL;
+}
+
+Field* Class::FindStaticField(String* name, String* type) {
   // Is the field in this class (or its interfaces), or any of its
   // superclasses (or their interfaces)?
   for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
diff --git a/src/object.h b/src/object.h
index 752d405..cabaac2 100644
--- a/src/object.h
+++ b/src/object.h
@@ -29,6 +29,7 @@
 #include "logging.h"
 #include "macros.h"
 #include "offsets.h"
+#include "primitive.h"
 #include "runtime.h"
 #include "stringpiece.h"
 #include "thread.h"
@@ -425,6 +426,14 @@
   // if type isn't yet resolved
   Class* GetTypeDuringLinking() const;
 
+  bool IsPrimitiveType() const;
+
+  Primitive::Type GetPrimitiveType() const;
+
+  size_t PrimitiveSize() const;
+
+  const char* GetTypeDescriptor() const;
+
   // Performs full resolution, may return null and set exceptions if type cannot
   // be resolved
   Class* GetType() const;
@@ -492,9 +501,9 @@
 
   Object* generic_type_;
 
-  const String* name_;
+  String* name_;
 
-  // Type of the field
+  // The possibly null type of the field
   mutable Class* type_;
 
   uint32_t generic_types_are_initialized_;
@@ -1263,19 +1272,6 @@
     kStatusInitialized = 7,  // ready to go
   };
 
-  enum PrimitiveType {
-    kPrimNot = 0,
-    kPrimBoolean,
-    kPrimByte,
-    kPrimChar,
-    kPrimShort,
-    kPrimInt,
-    kPrimLong,
-    kPrimFloat,
-    kPrimDouble,
-    kPrimVoid,
-  };
-
   Status GetStatus() const {
     DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
     return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), false));
@@ -1383,62 +1379,58 @@
     return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
   }
 
-  PrimitiveType GetPrimitiveType() const {
-    DCHECK_EQ(sizeof(PrimitiveType), sizeof(int32_t));
-    return static_cast<PrimitiveType>(
+  Primitive::Type GetPrimitiveType() const {
+    DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
+    return static_cast<Primitive::Type>(
         GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
   }
 
-  void SetPrimitiveType(PrimitiveType new_type) {
-    DCHECK_EQ(sizeof(PrimitiveType), sizeof(int32_t));
+  void SetPrimitiveType(Primitive::Type new_type) {
+    DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
     SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false);
   }
 
   // Returns true if the class is a primitive type.
   bool IsPrimitive() const {
-    return GetPrimitiveType() != kPrimNot;
+    return GetPrimitiveType() != Primitive::kPrimNot;
   }
 
   bool IsPrimitiveBoolean() const {
-    return GetPrimitiveType() == kPrimBoolean;
+    return GetPrimitiveType() == Primitive::kPrimBoolean;
   }
 
   bool IsPrimitiveByte() const {
-    return GetPrimitiveType() == kPrimByte;
+    return GetPrimitiveType() == Primitive::kPrimByte;
   }
 
   bool IsPrimitiveChar() const {
-    return GetPrimitiveType() == kPrimChar;
+    return GetPrimitiveType() == Primitive::kPrimChar;
   }
 
   bool IsPrimitiveShort() const {
-    return GetPrimitiveType() == kPrimShort;
+    return GetPrimitiveType() == Primitive::kPrimShort;
   }
 
   bool IsPrimitiveInt() const {
-    return GetPrimitiveType() == kPrimInt;
+    return GetPrimitiveType() == Primitive::kPrimInt;
   }
 
   bool IsPrimitiveLong() const {
-    return GetPrimitiveType() == kPrimLong;
+    return GetPrimitiveType() == Primitive::kPrimLong;
   }
 
   bool IsPrimitiveFloat() const {
-    return GetPrimitiveType() == kPrimFloat;
+    return GetPrimitiveType() == Primitive::kPrimFloat;
   }
 
   bool IsPrimitiveDouble() const {
-    return GetPrimitiveType() == kPrimDouble;
+    return GetPrimitiveType() == Primitive::kPrimDouble;
   }
 
   bool IsPrimitiveVoid() const {
-    return GetPrimitiveType() == kPrimVoid;
+    return GetPrimitiveType() == Primitive::kPrimVoid;
   }
 
-  size_t PrimitiveFieldSize() const;
-
-  size_t PrimitiveSize() const;
-
   // Depth of class from java.lang.Object
   size_t Depth() {
     size_t depth = 0;
@@ -1463,7 +1455,7 @@
   }
 
   size_t GetComponentSize() const {
-    return GetTypeSize(GetComponentType()->GetDescriptor());
+    return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
   }
 
   bool IsObjectClass() const {
@@ -1473,8 +1465,6 @@
   // Creates a raw object instance but does not invoke the default constructor.
   Object* AllocObject();
 
-  static size_t GetTypeSize(const String* descriptor);
-
   const String* GetDescriptor() const {
     const String* result = GetFieldObject<const String*>(
         OFFSET_OF_OBJECT_MEMBER(Class, descriptor_), false);
@@ -1923,14 +1913,18 @@
   void SetReferenceStaticOffsets(uint32_t new_reference_offsets);
 
   // Finds the given instance field in this class or a superclass.
-  Field* FindInstanceField(const StringPiece& name, Class* type);
+  Field* FindInstanceField(const StringPiece& name, const StringPiece& type);
+  Field* FindInstanceField(String* name, String* type);
 
-  Field* FindDeclaredInstanceField(const StringPiece& name, Class* type);
+  Field* FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type);
+  Field* FindDeclaredInstanceField(String* name, String* type);
 
   // Finds the given static field in this class or a superclass.
-  Field* FindStaticField(const StringPiece& name, Class* type);
+  Field* FindStaticField(const StringPiece& name, const StringPiece& type);
+  Field* FindStaticField(String* name, String* type);
 
-  Field* FindDeclaredStaticField(const StringPiece& name, Class* type);
+  Field* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type);
+  Field* FindDeclaredStaticField(String* name, String* type);
 
   pid_t GetClinitThreadId() const {
     DCHECK(IsIdxLoaded() || IsErroneous());
@@ -2058,8 +2052,8 @@
   // See also class_size_.
   size_t object_size_;
 
-  // primitive type index, or kPrimNot (0); set for generated prim classes
-  PrimitiveType primitive_type_;
+  // primitive type index, or Primitive::kPrimNot (0); set for generated prim classes
+  Primitive::Type primitive_type_;
 
   // Bitmap of offsets of ifields.
   uint32_t reference_instance_offsets_;
@@ -2178,8 +2172,8 @@
 
 inline void Field::SetOffset(MemberOffset num_bytes) {
   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
-  Class* type = GetTypeDuringLinking();
-  if (type != NULL && (type->IsPrimitiveDouble() || type->IsPrimitiveLong())) {
+  Primitive::Type type = GetPrimitiveType();
+  if (type == Primitive::kPrimDouble || type == Primitive::kPrimLong) {
     DCHECK_ALIGNED(num_bytes.Uint32Value(), 8);
   }
   SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), num_bytes.Uint32Value(), false);
diff --git a/src/object_test.cc b/src/object_test.cc
index db1d331..b09cff1 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -434,16 +434,16 @@
   ASSERT_TRUE(c != NULL);
 
   // Wrong type.
-  EXPECT_TRUE(c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("J")) == NULL);
-  EXPECT_TRUE(c->FindInstanceField("count", class_linker_->FindSystemClass("J")) == NULL);
+  EXPECT_TRUE(c->FindDeclaredInstanceField("count", "J") == NULL);
+  EXPECT_TRUE(c->FindInstanceField("count", "J") == NULL);
 
   // Wrong name.
-  EXPECT_TRUE(c->FindDeclaredInstanceField("Count", class_linker_->FindSystemClass("I")) == NULL);
-  EXPECT_TRUE(c->FindInstanceField("Count", class_linker_->FindSystemClass("I")) == NULL);
+  EXPECT_TRUE(c->FindDeclaredInstanceField("Count", "I") == NULL);
+  EXPECT_TRUE(c->FindInstanceField("Count", "I") == NULL);
 
   // Right name and type.
-  Field* f1 = c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("I"));
-  Field* f2 = c->FindInstanceField("count", class_linker_->FindSystemClass("I"));
+  Field* f1 = c->FindDeclaredInstanceField("count", "I");
+  Field* f2 = c->FindInstanceField("count", "I");
   EXPECT_TRUE(f1 != NULL);
   EXPECT_TRUE(f2 != NULL);
   EXPECT_EQ(f1, f2);
@@ -454,9 +454,9 @@
   c = class_linker_->FindSystemClass("Ljava/lang/StringBuilder;");
   ASSERT_TRUE(c != NULL);
   // No StringBuilder.count...
-  EXPECT_TRUE(c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("I")) == NULL);
+  EXPECT_TRUE(c->FindDeclaredInstanceField("count", "I") == NULL);
   // ...but there is an AbstractStringBuilder.count.
-  EXPECT_TRUE(c->FindInstanceField("count", class_linker_->FindSystemClass("I")) != NULL);
+  EXPECT_TRUE(c->FindInstanceField("count", "I") != NULL);
 }
 
 TEST_F(ObjectTest, FindStaticField) {
@@ -466,16 +466,16 @@
   ASSERT_TRUE(c != NULL);
 
   // Wrong type.
-  EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("I")) == NULL);
-  EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("I")) == NULL);
+  EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
+  EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
 
   // Wrong name.
-  EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;")) == NULL);
-  EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;")) == NULL);
+  EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
+  EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
 
   // Right name and type.
-  Field* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;"));
-  Field* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;"));
+  Field* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+  Field* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
   EXPECT_TRUE(f1 != NULL);
   EXPECT_TRUE(f2 != NULL);
   EXPECT_EQ(f1, f2);
diff --git a/src/primitive.h b/src/primitive.h
new file mode 100644
index 0000000..259378d
--- /dev/null
+++ b/src/primitive.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_PRIMITIVE_H_
+#define ART_SRC_PRIMITIVE_H_
+
+#include <sys/types.h>
+
+#include "logging.h"
+#include "macros.h"
+
+namespace art {
+
+class Object;
+
+class Primitive {
+ public:
+  enum Type {
+    kPrimNot = 0,
+    kPrimBoolean,
+    kPrimByte,
+    kPrimChar,
+    kPrimShort,
+    kPrimInt,
+    kPrimLong,
+    kPrimFloat,
+    kPrimDouble,
+    kPrimVoid,
+  };
+
+  static Type GetType(char type) {
+    switch (type) {
+      case 'B':
+        return kPrimByte;
+      case 'C':
+        return kPrimChar;
+      case 'D':
+        return kPrimDouble;
+      case 'F':
+        return kPrimFloat;
+      case 'I':
+        return kPrimInt;
+      case 'J':
+        return kPrimLong;
+      case 'S':
+        return kPrimShort;
+      case 'Z':
+        return kPrimBoolean;
+      case 'V':
+        return kPrimVoid;
+      default:
+        return kPrimNot;
+    }
+  }
+
+  static size_t ComponentSize(Type type) {
+    switch (type) {
+      case kPrimBoolean:
+      case kPrimByte:    return 1;
+      case kPrimChar:
+      case kPrimShort:   return 2;
+      case kPrimInt:
+      case kPrimFloat:   return 4;
+      case kPrimLong:
+      case kPrimDouble:  return 8;
+      case kPrimNot:     return sizeof(Object*);
+      default:
+        LOG(FATAL) << "Invalid type " << static_cast<int>(type);
+        return 0;
+    }
+  }
+
+  static size_t FieldSize(Type type) {
+    return ComponentSize(type) <= 4 ? 4 : 8;
+  }
+
+  static char DescriptorChar(Type type) {
+    switch (type) {
+      case kPrimBoolean:
+        return 'Z';
+      case kPrimByte:
+        return 'B';
+      case kPrimChar:
+        return 'C';
+      case kPrimShort:
+        return 'S';
+      case kPrimInt:
+        return 'I';
+      case kPrimFloat:
+        return 'J';
+      case kPrimLong:
+        return 'J';
+      case kPrimDouble:
+        return 'D';
+      default:
+        LOG(FATAL) << "Primitive char conversion on invalid type " << static_cast<int>(type);
+        return 0;
+    }
+  }
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Primitive);
+};
+
+}  // namespace art
+
+#endif  // ART_SRC_PRIMITIVE_H_
diff --git a/src/reflection.cc b/src/reflection.cc
index 86b4b09..b367ad3 100644
--- a/src/reflection.cc
+++ b/src/reflection.cc
@@ -114,7 +114,7 @@
   }
 
   // Box if necessary and return.
-  BoxPrimitive(env, m->GetReturnType(), value);
+  BoxPrimitive(env, m->GetReturnType()->GetPrimitiveType(), value);
   return AddLocalReference<jobject>(env, value.l);
 }
 
@@ -153,66 +153,65 @@
  * 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();
+bool ConvertPrimitiveValue(Primitive::Type srcType, Primitive::Type dstType,
+                           const JValue& src, JValue& dst) {
   switch (dstType) {
-  case Class::kPrimBoolean:
-  case Class::kPrimChar:
-  case Class::kPrimByte:
+  case Primitive::kPrimBoolean:
+  case Primitive::kPrimChar:
+  case Primitive::kPrimByte:
     if (srcType == dstType) {
       dst.i = src.i;
       return true;
     }
     break;
-  case Class::kPrimShort:
-    if (srcType == Class::kPrimByte || srcType == Class::kPrimShort) {
+  case Primitive::kPrimShort:
+    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimShort) {
       dst.i = src.i;
       return true;
     }
     break;
-  case Class::kPrimInt:
-    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
-        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+  case Primitive::kPrimInt:
+    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
       dst.i = src.i;
       return true;
     }
     break;
-  case Class::kPrimLong:
-    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
-        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+  case Primitive::kPrimLong:
+    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
       dst.j = src.i;
       return true;
-    } else if (srcType == Class::kPrimLong) {
+    } else if (srcType == Primitive::kPrimLong) {
       dst.j = src.j;
       return true;
     }
     break;
-  case Class::kPrimFloat:
-    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
-        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+  case Primitive::kPrimFloat:
+    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
       dst.f = src.i;
       return true;
-    } else if (srcType == Class::kPrimLong) {
+    } else if (srcType == Primitive::kPrimLong) {
       dst.f = src.j;
       return true;
-    } else if (srcType == Class::kPrimFloat) {
+    } else if (srcType == Primitive::kPrimFloat) {
       dst.i = src.i;
       return true;
     }
     break;
-  case Class::kPrimDouble:
-    if (srcType == Class::kPrimByte || srcType == Class::kPrimChar ||
-        srcType == Class::kPrimShort || srcType == Class::kPrimInt) {
+  case Primitive::kPrimDouble:
+    if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar ||
+        srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) {
       dst.d = src.i;
       return true;
-    } else if (srcType == Class::kPrimLong) {
+    } else if (srcType == Primitive::kPrimLong) {
       dst.d = src.j;
       return true;
-    } else if (srcType == Class::kPrimFloat) {
+    } else if (srcType == Primitive::kPrimFloat) {
       dst.d = src.f;
       return true;
-    } else if (srcType == Class::kPrimDouble) {
+    } else if (srcType == Primitive::kPrimDouble) {
       dst.j = src.j;
       return true;
     }
@@ -221,59 +220,59 @@
     break;
   }
   Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
-      "invalid primitive conversion from %s to %s",
-      PrettyDescriptor(src_class->GetDescriptor()).c_str(),
-      PrettyDescriptor(dst_class->GetDescriptor()).c_str());
+                                        "invalid primitive conversion from %s to %s",
+                                        PrettyDescriptor(srcType).c_str(),
+                                        PrettyDescriptor(dstType).c_str());
   return false;
 }
 
-void BoxPrimitive(JNIEnv* env, Class* src_class, JValue& value) {
-  if (!src_class->IsPrimitive()) {
+void BoxPrimitive(JNIEnv* env, Primitive::Type src_class, JValue& value) {
+  if (src_class == Primitive::kPrimNot) {
     return;
   }
 
   Method* m = NULL;
   UniquePtr<byte[]> args(new byte[8]);
   memset(&args[0], 0, 8);
-  switch (src_class->GetPrimitiveType()) {
-  case Class::kPrimBoolean:
+  switch (src_class) {
+  case Primitive::kPrimBoolean:
     m = gBoolean_valueOf;
     *reinterpret_cast<uint32_t*>(&args[0]) = value.z;
     break;
-  case Class::kPrimByte:
+  case Primitive::kPrimByte:
     m = gByte_valueOf;
     *reinterpret_cast<uint32_t*>(&args[0]) = value.b;
     break;
-  case Class::kPrimChar:
+  case Primitive::kPrimChar:
     m = gCharacter_valueOf;
     *reinterpret_cast<uint32_t*>(&args[0]) = value.c;
     break;
-  case Class::kPrimDouble:
+  case Primitive::kPrimDouble:
     m = gDouble_valueOf;
     *reinterpret_cast<double*>(&args[0]) = value.d;
     break;
-  case Class::kPrimFloat:
+  case Primitive::kPrimFloat:
     m = gFloat_valueOf;
     *reinterpret_cast<float*>(&args[0]) = value.f;
     break;
-  case Class::kPrimInt:
+  case Primitive::kPrimInt:
     m = gInteger_valueOf;
     *reinterpret_cast<uint32_t*>(&args[0]) = value.i;
     break;
-  case Class::kPrimLong:
+  case Primitive::kPrimLong:
     m = gLong_valueOf;
     *reinterpret_cast<uint64_t*>(&args[0]) = value.j;
     break;
-  case Class::kPrimShort:
+  case Primitive::kPrimShort:
     m = gShort_valueOf;
     *reinterpret_cast<uint32_t*>(&args[0]) = value.s;
     break;
-  case Class::kPrimVoid:
+  case Primitive::kPrimVoid:
     // There's no such thing as a void field, and void methods invoked via reflection return null.
     value.l = NULL;
     return;
   default:
-    LOG(FATAL) << PrettyClass(src_class);
+    LOG(FATAL) << static_cast<int>(src_class);
   }
 
   Thread* self = Thread::Current();
@@ -282,7 +281,7 @@
 }
 
 bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value) {
-  if (dst_class->GetPrimitiveType() == Class::kPrimNot) {
+  if (!dst_class->IsPrimitive()) {
     if (o != NULL && !o->InstanceOf(dst_class)) {
       jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
           "expected object of type %s, but got %s",
@@ -292,7 +291,7 @@
     }
     unboxed_value.l = o;
     return true;
-  } else if (dst_class->GetPrimitiveType() == Class::kPrimVoid) {
+  } else if (dst_class->GetPrimitiveType() == Primitive::kPrimVoid) {
     Thread::Current()->ThrowNewException("Ljava/lang/IllegalArgumentException;",
         "can't unbox to void");
     return false;
@@ -339,7 +338,8 @@
     return false;
   }
 
-  return ConvertPrimitiveValue(src_class, dst_class, boxed_value, unboxed_value);
+  return ConvertPrimitiveValue(src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(),
+                               boxed_value, unboxed_value);
 }
 
 }  // namespace art
diff --git a/src/reflection.h b/src/reflection.h
index 2d18331..e0263bd 100644
--- a/src/reflection.h
+++ b/src/reflection.h
@@ -18,6 +18,7 @@
 #define ART_SRC_REFLECTION_H_
 
 #include "jni.h"
+#include "primitive.h"
 
 namespace art {
 
@@ -26,10 +27,10 @@
 class Object;
 
 void InitBoxingMethods(JNIEnv* env);
-void BoxPrimitive(JNIEnv* env, Class* src_class, JValue& value);
+void BoxPrimitive(JNIEnv* env, Primitive::Type src_class, JValue& value);
 bool UnboxPrimitive(JNIEnv* env, Object* o, Class* dst_class, JValue& unboxed_value);
 
-bool ConvertPrimitiveValue(Class* src_class, Class* dst_class, const JValue& src, JValue& dst);
+bool ConvertPrimitiveValue(Primitive::Type src_class, Primitive::Type dst_class, const JValue& src, JValue& dst);
 
 jobject InvokeMethod(JNIEnv* env, jobject method, jobject receiver, jobject args, jobject params);
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 5f2eddd..c777fa1 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -495,7 +495,11 @@
   thread_list_ = new ThreadList(options->IsVerbose("thread"));
   intern_table_ = new InternTable;
 
-  Heap::Init(options->heap_initial_size_, options->heap_maximum_size_, options->images_);
+  Heap::Init(options->IsVerbose("heap"),
+             options->IsVerbose("gc"),
+             options->heap_initial_size_,
+             options->heap_maximum_size_,
+             options->images_);
 
   BlockSignals();
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index c7140f1..35d1103 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -184,7 +184,7 @@
   const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
 
   const DexFile::FieldId& id = dex_file.GetFieldId(ref);
-  std::string class_name(PrettyDescriptor(dex_file.GetFieldClassDescriptor(id)));
+  std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
   const char* field_name = dex_file.dexStringById(id.name_idx_);
   if (!access) {
     return class_name + "." + field_name;
@@ -206,7 +206,7 @@
   const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
 
   const DexFile::MethodId& id = dex_file.GetMethodId(ref);
-  std::string class_name(PrettyDescriptor(dex_file.GetMethodClassDescriptor(id)));
+  std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
   const char* method_name = dex_file.dexStringById(id.name_idx_);
   if (!access) {
     return class_name + "." + method_name;
@@ -496,16 +496,14 @@
                                            Thread* self, Method** sp) {
   Field* field = FindFieldFast(field_idx, referrer);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) {
+    if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
       return field->Get32(NULL);
     }
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
-    Class* type = field->GetType();
-    if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
+    if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted read of 32-bit primitive on field '%s'",
                                PrettyField(field, true).c_str());
@@ -520,16 +518,14 @@
                                            Thread* self, Method** sp) {
   Field* field = FindFieldFast(field_idx, referrer);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) {
+    if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
       return field->Get64(NULL);
     }
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
-    Class* type = field->GetType();
-    if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+    if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t)) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted read of 64-bit primitive on field '%s'",
                                PrettyField(field, true).c_str());
@@ -544,16 +540,14 @@
                                            Thread* self, Method** sp) {
   Field* field = FindFieldFast(field_idx, referrer);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (LIKELY(!type->IsPrimitive())) {
+    if (LIKELY(!field->IsPrimitiveType())) {
       return field->GetObj(NULL);
     }
   }
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
-    Class* type = field->GetType();
-    if (type->IsPrimitive()) {
+    if (field->IsPrimitiveType()) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted read of reference on primitive field '%s'",
                                PrettyField(field, true).c_str());
@@ -568,8 +562,7 @@
                                        uint32_t new_value, Thread* self, Method** sp) {
   Field* field = FindFieldFast(field_idx, referrer);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int32_t))) {
+    if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
       field->Set32(NULL, new_value);
       return 0;  // success
     }
@@ -577,8 +570,7 @@
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
-    Class* type = field->GetType();
-    if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
+    if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted write of 32-bit primitive to field '%s'",
                                PrettyField(field, true).c_str());
@@ -594,8 +586,7 @@
                                       uint64_t new_value, Thread* self, Method** sp) {
   Field* field = FindFieldFast(field_idx, referrer);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (LIKELY(type->IsPrimitive() && type->PrimitiveSize() == sizeof(int64_t))) {
+    if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
       field->Set64(NULL, new_value);
       return 0;  // success
     }
@@ -603,8 +594,7 @@
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   field = FindFieldFromCode(field_idx, referrer, true);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (UNLIKELY(!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t))) {
+    if (UNLIKELY(!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t))) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted write of 64-bit primitive to field '%s'",
                                PrettyField(field, true).c_str());
@@ -620,8 +610,7 @@
                                        Object* new_value, Thread* self, Method** sp) {
   Field* field = FindFieldFast(field_idx, referrer);
   if (LIKELY(field != NULL)) {
-    Class* type = field->GetType();
-    if (LIKELY(!type->IsPrimitive())) {
+    if (LIKELY(!field->IsPrimitiveType())) {
       field->SetObj(NULL, new_value);
       return 0;  // success
     }
@@ -629,8 +618,7 @@
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
   field = FindFieldFromCode(field_idx, referrer, true);
   if (field != NULL) {
-    Class* type = field->GetType();
-    if (type->IsPrimitive()) {
+    if (field->IsPrimitiveType()) {
       self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
                                "Attempted write of reference to primitive field '%s'",
                                PrettyField(field, true).c_str());
@@ -1021,7 +1009,7 @@
         uint64_t high_half = *reinterpret_cast<uint32_t*>(stack_args + (13 * kPointerSize));
         val.j = (val.j & 0xffffffffULL) | (high_half << 32);
       }
-      BoxPrimitive(env, param_type, val);
+      BoxPrimitive(env, param_type->GetPrimitiveType(), val);
       if (self->IsExceptionPending()) {
         return;
       }
@@ -1040,7 +1028,7 @@
       obj = self->DecodeJObject(*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)));
     } else {
       JValue val = *reinterpret_cast<JValue*>(stack_args + (cur_arg * kPointerSize));
-      BoxPrimitive(env, param_type, val);
+      BoxPrimitive(env, param_type->GetPrimitiveType(), val);
       if (self->IsExceptionPending()) {
         return;
       }
diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc
index 851aab7..41d0fe4 100644
--- a/src/signal_catcher.cc
+++ b/src/signal_catcher.cc
@@ -116,9 +116,11 @@
 
   runtime->Dump(os);
 
-  std::string maps;
-  if (ReadFileToString("/proc/self/maps", &maps)) {
-    os << "/proc/self/maps:\n" << maps;
+  if (false) {
+    std::string maps;
+    if (ReadFileToString("/proc/self/maps", &maps)) {
+      os << "/proc/self/maps:\n" << maps;
+    }
   }
 
   os << "----- end " << getpid() << " -----\n";
diff --git a/src/thread.cc b/src/thread.cc
index 2736140..f4ca2ab 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -642,9 +642,9 @@
 }
 
 // TODO: make more accessible?
-Field* FindFieldOrDie(Class* c, const char* name, Class* type) {
-  Field* f = c->FindDeclaredInstanceField(name, type);
-  CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << PrettyClass(type);
+Field* FindFieldOrDie(Class* c, const char* name, const char* descriptor) {
+  Field* f = c->FindDeclaredInstanceField(name, descriptor);
+  CHECK(f != NULL) << PrettyClass(c) << " " << name << " " << descriptor;
   return f;
 }
 
@@ -659,25 +659,21 @@
   // Now the ClassLinker is ready, we can find the various Class*, Field*, and Method*s we need.
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
 
-  Class* boolean_class = FindPrimitiveClassOrDie(class_linker, 'Z');
-  Class* int_class = FindPrimitiveClassOrDie(class_linker, 'I');
-  Class* ClassLoader_class = FindClassOrDie(class_linker, "Ljava/lang/ClassLoader;");
-  Class* String_class = FindClassOrDie(class_linker, "Ljava/lang/String;");
   Class* Thread_class = FindClassOrDie(class_linker, "Ljava/lang/Thread;");
   Class* ThreadGroup_class = FindClassOrDie(class_linker, "Ljava/lang/ThreadGroup;");
   Class* UncaughtExceptionHandler_class = FindClassOrDie(class_linker, "Ljava/lang/Thread$UncaughtExceptionHandler;");
   gThreadLock = FindClassOrDie(class_linker, "Ljava/lang/ThreadLock;");
   gThrowable = FindClassOrDie(class_linker, "Ljava/lang/Throwable;");
 
-  gThread_daemon = FindFieldOrDie(Thread_class, "daemon", boolean_class);
-  gThread_group = FindFieldOrDie(Thread_class, "group", ThreadGroup_class);
-  gThread_lock = FindFieldOrDie(Thread_class, "lock", gThreadLock);
-  gThread_name = FindFieldOrDie(Thread_class, "name", String_class);
-  gThread_priority = FindFieldOrDie(Thread_class, "priority", int_class);
-  gThread_uncaughtHandler = FindFieldOrDie(Thread_class, "uncaughtHandler", UncaughtExceptionHandler_class);
-  gThread_vmData = FindFieldOrDie(Thread_class, "vmData", int_class);
-  gThreadGroup_name = FindFieldOrDie(ThreadGroup_class, "name", String_class);
-  gThreadLock_thread = FindFieldOrDie(gThreadLock, "thread", Thread_class);
+  gThread_daemon = FindFieldOrDie(Thread_class, "daemon", "Z");
+  gThread_group = FindFieldOrDie(Thread_class, "group", "Ljava/lang/ThreadGroup;");
+  gThread_lock = FindFieldOrDie(Thread_class, "lock", "Ljava/lang/ThreadLock;");
+  gThread_name = FindFieldOrDie(Thread_class, "name", "Ljava/lang/String;");
+  gThread_priority = FindFieldOrDie(Thread_class, "priority", "I");
+  gThread_uncaughtHandler = FindFieldOrDie(Thread_class, "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
+  gThread_vmData = FindFieldOrDie(Thread_class, "vmData", "I");
+  gThreadGroup_name = FindFieldOrDie(ThreadGroup_class, "name", "Ljava/lang/String;");
+  gThreadLock_thread = FindFieldOrDie(gThreadLock, "thread", "Ljava/lang/Thread;");
 
   gThread_run = FindMethodOrDie(Thread_class, "run", "()V");
   gThreadGroup_removeThread = FindMethodOrDie(ThreadGroup_class, "removeThread", "(Ljava/lang/Thread;)V");
@@ -688,7 +684,7 @@
   Thread* self = Thread::Current();
   self->CreatePeer("main", false);
 
-  const Field* Thread_contextClassLoader = FindFieldOrDie(Thread_class , "contextClassLoader", ClassLoader_class);
+  const Field* Thread_contextClassLoader = FindFieldOrDie(Thread_class , "contextClassLoader", "Ljava/lang/ClassLoader;");
   Thread_contextClassLoader->SetObject(self->GetPeer(), self->GetClassLoaderOverride());
 }
 
@@ -1235,7 +1231,15 @@
 }
 
 void Thread::DumpFromGdb() const {
-  Dump(std::cerr);
+  std::ostringstream ss;
+  Dump(ss);
+  std::string str = ss.str();
+  // log to stderr for debugging command line processes
+  std::cerr << str;
+#ifdef HAVE_ANDROID_OS
+  // log to logcat for debugging frameworks processes
+  LOG(INFO) << str;
+#endif
 }
 
 class CatchBlockStackVisitor : public Thread::StackVisitor {
diff --git a/src/utils.cc b/src/utils.cc
index 3922033..a74e231 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -110,13 +110,19 @@
   return result;
 }
 
+std::string PrettyDescriptor(Primitive::Type type) {
+  char descriptor_char = Primitive::DescriptorChar(type);
+  std::string descriptor_string(1, descriptor_char);
+  return PrettyDescriptor(descriptor_string);
+}
+
 std::string PrettyField(const Field* f, bool with_type) {
   if (f == NULL) {
     return "null";
   }
   std::string result;
   if (with_type) {
-    result += PrettyDescriptor(f->GetType()->GetDescriptor());
+    result += PrettyDescriptor(f->GetTypeDescriptor());
     result += ' ';
   }
   result += PrettyDescriptor(f->GetDeclaringClass()->GetDescriptor());
diff --git a/src/utils.h b/src/utils.h
index 53a0378..66cda54 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -5,6 +5,7 @@
 
 #include "globals.h"
 #include "logging.h"
+#include "primitive.h"
 #include "stringpiece.h"
 #include "stringprintf.h"
 
@@ -156,6 +157,7 @@
 // "java.lang.String[]", and so forth.
 std::string PrettyDescriptor(const String* descriptor);
 std::string PrettyDescriptor(const std::string& descriptor);
+std::string PrettyDescriptor(Primitive::Type type);
 
 // Returns a human-readable signature for 'f'. Something like "a.b.C.f" or
 // "int a.b.C.f" (depending on the value of 'with_type').
diff --git a/src/utils_test.cc b/src/utils_test.cc
index f1944f0..df47d79 100644
--- a/src/utils_test.cc
+++ b/src/utils_test.cc
@@ -92,14 +92,12 @@
   EXPECT_EQ("null", PrettyField(NULL));
 
   Class* java_lang_String = class_linker_->FindSystemClass("Ljava/lang/String;");
-  Class* int_class = class_linker_->FindPrimitiveClass('I');
-  Class* char_array_class = class_linker_->FindSystemClass("[C");
 
   Field* f;
-  f = java_lang_String->FindDeclaredInstanceField("count", int_class);
+  f = java_lang_String->FindDeclaredInstanceField("count", "I");
   EXPECT_EQ("int java.lang.String.count", PrettyField(f));
   EXPECT_EQ("java.lang.String.count", PrettyField(f, false));
-  f = java_lang_String->FindDeclaredInstanceField("value", char_array_class);
+  f = java_lang_String->FindDeclaredInstanceField("value", "[C");
   EXPECT_EQ("char[] java.lang.String.value", PrettyField(f));
   EXPECT_EQ("java.lang.String.value", PrettyField(f, false));
 }