Fix GarbageCollector to work with VERIFY_OBJECT_ENABLED

There were two problems with the GC:
1.) roots were being missed for most of the C++ fields
2.) Heap::RecordFree(Object) was not being called, only Space::Free

To solve #1, added all C++ shadow fields to libcore.
This involed updating dalvik to cope with the new sizes and offsets.
This had the positive side effect of allowing a lot of special cases
in the object scanning and image writing.

To solve #2, added a call to the now public Heap::RecordFree from MarkSweep

Given the now better working GC:
- Reenabled HeapTest.GarbageCollectClassLinkerInit which is now passing.
- ImageWriter now GC's before writing an image to avoid garbage.

Change-Id: Ie7d1cc89e0bcf314cb37f0cabcb8593bf6e4d4be
diff --git a/src/class_linker.cc b/src/class_linker.cc
index b533a11..0df0cb7 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -102,7 +102,6 @@
   object_array_class->SetArrayRank(1);
   object_array_class->SetComponentType(java_lang_Object);
 
-
   // Setup the char[] class to be used for String
   Class* char_array_class = AllocClass(java_lang_Class, sizeof(Class));
   char_array_class->SetArrayRank(1);
@@ -256,7 +255,6 @@
 
   // run Class, Field, and Method through FindSystemClass.
   // this initializes their dex_cache_ fields and register them in classes_.
-  // we also override their object_size_ values to accommodate the extra C++ fields.
   Class* Class_class = FindSystemClass("Ljava/lang/Class;");
   CHECK_EQ(java_lang_Class, Class_class);
   // No sanity check on size as Class is variably sized
@@ -264,14 +262,10 @@
   java_lang_reflect_Field->SetStatus(Class::kStatusNotReady);
   Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
   CHECK_EQ(java_lang_reflect_Field, Field_class);
-  CHECK_LT(java_lang_reflect_Field->GetObjectSize(), sizeof(Field));
-  java_lang_reflect_Field->SetObjectSize(sizeof(Field));
 
   java_lang_reflect_Method->SetStatus(Class::kStatusNotReady);
   Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
   CHECK_EQ(java_lang_reflect_Method, Method_class);
-  CHECK_LT(java_lang_reflect_Method->GetObjectSize(), sizeof(Method));
-  java_lang_reflect_Method->SetObjectSize(sizeof(Method));
 
   // java.lang.ref classes need to be specially flagged, but otherwise are normal classes
   Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
@@ -1076,7 +1070,11 @@
   }
   DCHECK_LE(1, new_class->GetArrayRank());
   DCHECK(new_class->GetComponentType() != NULL);
-  new_class->SetDescriptor(String::AllocFromModifiedUtf8(descriptor.ToString().c_str()));
+  if (new_class->GetDescriptor() != NULL) {
+    DCHECK(new_class->GetDescriptor()->Equals(descriptor));
+  } else {
+    new_class->SetDescriptor(String::AllocFromModifiedUtf8(descriptor.ToString().c_str()));
+  }
   Class* java_lang_Object = GetClassRoot(kJavaLangObject);
   new_class->SetSuperClass(java_lang_Object);
   new_class->SetVTable(java_lang_Object->GetVTable());
@@ -1844,26 +1842,21 @@
       instance ? klass->GetIFields() : klass->GetSFields();
   // Fields updated at end of LinkFields
   size_t num_reference_fields;
-  size_t size;
 
   // Initialize size and field_offset
-  MemberOffset field_offset = Class::FieldsOffset();
+  size_t size;
+  MemberOffset field_offset(0);
   if (instance) {
     Class* super_class = klass->GetSuperClass();
     if (super_class != NULL) {
       CHECK(super_class->IsResolved());
       field_offset = MemberOffset(super_class->GetObjectSize());
-      if (field_offset.Uint32Value() == 0u) {
-        field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_);
-      }
-    } else {
-      field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_);
     }
     size = field_offset.Uint32Value();
   } else {
     size = klass->GetClassSize();
+    field_offset = Class::FieldsOffset();
   }
-  DCHECK_LE(CLASS_SMALLEST_OFFSET, size);
 
   CHECK((num_fields == 0) == (fields == NULL));
 
@@ -1993,7 +1986,6 @@
   }
 #endif
   size = field_offset.Uint32Value();
-  DCHECK_LE(CLASS_SMALLEST_OFFSET, size);
   // Update klass
   if(instance) {
     klass->SetNumReferenceInstanceFields(num_reference_fields);
@@ -2041,7 +2033,6 @@
     // object, not the offset into instance data
     const Field* field = fields->Get(i);
     MemberOffset byte_offset = field->GetOffsetDuringLinking();
-    CHECK_GE(byte_offset.Uint32Value(), CLASS_SMALLEST_OFFSET);
     CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
     if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) {
       uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset.Uint32Value());
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 607382b..3362fdc 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -320,7 +320,10 @@
   EXPECT_FALSE(JavaLangObject->IsSynthetic());
   EXPECT_EQ(2U, JavaLangObject->NumDirectMethods());
   EXPECT_EQ(11U, JavaLangObject->NumVirtualMethods());
-  EXPECT_EQ(0U, JavaLangObject->NumInstanceFields());
+  EXPECT_EQ(2U, JavaLangObject->NumInstanceFields());
+  EXPECT_TRUE(JavaLangObject->GetInstanceField(0)->GetName()->Equals("shadow$_klass_"));
+  EXPECT_TRUE(JavaLangObject->GetInstanceField(1)->GetName()->Equals("shadow$_monitor_"));
+
   EXPECT_EQ(0U, JavaLangObject->NumStaticFields());
   EXPECT_EQ(0U, JavaLangObject->NumInterfaces());
 
@@ -369,68 +372,265 @@
   AssertDexFile(java_lang_dex_file_.get(), NULL);
 }
 
+struct CheckOffset {
+  size_t cpp_offset;
+  const char* java_name;
+  CheckOffset(size_t c, const char* j) : cpp_offset(c), java_name(j) {}
+};
+
+struct CheckOffsets {
+  size_t s;
+  std::string c;
+  std::vector<CheckOffset> o;
+
+  bool Check() {
+    Class* klass = Runtime::Current()->GetClassLinker()->FindSystemClass(c);
+    CHECK(klass != NULL) << c;
+
+    bool error = false;
+
+    if (!klass->IsClassClass())
+      if (s != klass->GetObjectSize()) {
+        LG << "Class size mismatch:"
+           << " class=" << c
+           << " Java=" << klass->GetObjectSize()
+           << " C++=" << s;
+      error = true;
+    }
+
+    CHECK_EQ(o.size(), klass->NumInstanceFields());
+    for (size_t i = 0; i < o.size(); i++) {
+      Field* field = klass->GetInstanceField(i);
+      if (!field->GetName()->Equals(o[i].java_name)) {
+        error = true;
+      }
+    }
+    if (error) {
+      for (size_t i = 0; i < o.size(); i++) {
+        CheckOffset& offset = o[i];
+        Field* field = klass->GetInstanceField(i);
+        if (!field->GetName()->Equals(o[i].java_name)) {
+          LG << "JAVA FIELD ORDER MISMATCH NEXT LINE:";
+        }
+        LG << "Java field order:"
+           << " i=" << i << " class=" << c
+           << " Java=" << field->GetName()->ToModifiedUtf8()
+           << " CheckOffsets=" << offset.java_name;
+      }
+    }
+
+    for (size_t i = 0; i < o.size(); i++) {
+      CheckOffset& offset = o[i];
+      Field* field = klass->GetInstanceField(i);
+      if (field->GetOffset().Uint32Value() != offset.cpp_offset) {
+        error = true;
+      }
+    }
+    if (error) {
+      for (size_t i = 0; i < o.size(); i++) {
+        CheckOffset& offset = o[i];
+        Field* field = klass->GetInstanceField(i);
+        if (field->GetOffset().Uint32Value() != offset.cpp_offset) {
+          LG << "OFFSET MISMATCH NEXT LINE:";
+        }
+        LG << "Offset: class=" << c << " field=" << offset.java_name
+           << " Java=" << field->GetOffset().Uint32Value() << " C++=" << offset.cpp_offset;
+      }
+    }
+
+    return !error;
+  };
+};
+
+struct ObjectOffsets : public CheckOffsets {
+  ObjectOffsets() {
+    s = sizeof(Object);
+    c = "Ljava/lang/Object;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Object, klass_),   "shadow$_klass_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Object, monitor_), "shadow$_monitor_"));
+  };
+};
+
+struct AccessibleObjectOffsets : public CheckOffsets {
+  AccessibleObjectOffsets() {
+    s = sizeof(AccessibleObject);
+    c = "Ljava/lang/reflect/AccessibleObject;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(AccessibleObject, java_flag_), "flag"));
+  };
+};
+
+struct FieldOffsets : public CheckOffsets {
+  FieldOffsets() {
+    s = sizeof(Field);
+    c = "Ljava/lang/reflect/Field;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, declaring_class_),               "declaringClass"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, generic_type_),                  "genericType"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, type_),                          "type"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, name_),                          "name"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, access_flags_),                  "shadow$_access_flags_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, offset_),                        "shadow$_offset_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, type_idx_),                      "shadow$_type_idx_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, slot_),                          "slot"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Field, generic_types_are_initialized_), "genericTypesAreInitialized"));
+  };
+};
+
+struct MethodOffsets : public CheckOffsets {
+  MethodOffsets() {
+    s = sizeof(Method);
+    c = "Ljava/lang/reflect/Method;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, declaring_class_),                      "declaringClass"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_exception_types_),                 "exceptionTypes"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_formal_type_parameters_),          "formalTypeParameters"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_exception_types_),         "genericExceptionTypes"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_parameter_types_),         "genericParameterTypes"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_return_type_),             "genericReturnType"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, signature_),                            "shadow$_signature_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, name_),                                 "name"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_parameter_types_),                 "parameterTypes"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_return_type_),                     "returnType"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, mapping_table_),                        "shadow$_mapping_table_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, invoke_stub_array_),                    "shadow$_invoke_stub_array_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_array_),                           "shadow$_code_array_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_strings_),                    "shadow$_dex_cache_strings_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_types_),             "shadow$_dex_cache_resolved_types_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_code_and_direct_methods_),    "shadow$_dex_cache_code_and_direct_methods_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_initialized_static_storage_), "shadow$_dex_cache_initialized_static_storage_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_fields_),            "shadow$_dex_cache_resolved_fields_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, dex_cache_resolved_methods_),           "shadow$_dex_cache_resolved_methods_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, core_spill_mask_),                      "shadow$_core_spill_mask_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_item_offset_),                     "shadow$_code_item_offset_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, fp_spill_mask_),                        "shadow$_fp_spill_mask_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, frame_size_in_bytes_),                  "shadow$_frame_size_in_bytes_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, invoke_stub_),                          "shadow$_invoke_stub_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, code_),                                 "shadow$_code_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_return_type_idx_),                 "shadow$_java_return_type_idx_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, access_flags_),                         "shadow$_access_flags_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, method_index_),                         "shadow$_method_index_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, native_method_),                        "shadow$_native_method_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_ins_),                              "shadow$_num_ins_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_outs_),                             "shadow$_num_outs_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, num_registers_),                        "shadow$_num_registers_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, proto_idx_),                            "shadow$_proto_idx_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, return_pc_offset_in_bytes_),            "shadow$_return_pc_offset_in_bytes_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, shorty_),                               "shadow$_shorty_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_generic_types_are_initialized_),   "genericTypesAreInitialized"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Method, java_slot_),                            "slot"));
+  };
+};
+
+struct ClassOffsets : public CheckOffsets {
+  ClassOffsets() {
+    s = sizeof(Class);
+    c = "Ljava/lang/Class;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, name_),                          "name"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, vtable_),                        "shadow$_vtable_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, virtual_methods_),               "shadow$_virtual_methods_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, class_loader_),                  "shadow$_class_loader_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, verify_error_class_),            "shadow$_verify_error_class_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, super_class_),                   "shadow$_super_class_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, component_type_),                "shadow$_component_type_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, descriptor_),                    "shadow$_descriptor_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, dex_cache_),                     "shadow$_dex_cache_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, direct_methods_),                "shadow$_direct_methods_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, ifields_),                       "shadow$_ifields_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, sfields_),                       "shadow$_sfields_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, interfaces_type_idx_),           "shadow$_interfaces_type_idx_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, interfaces_),                    "shadow$_interfaces_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, ifvi_pool_count_),               "shadow$_ifvi_pool_count_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, ifvi_pool_),                     "shadow$_ifvi_pool_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, iftable_count_),                 "shadow$_iftable_count_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, num_reference_instance_fields_), "shadow$_num_reference_instance_fields_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, num_reference_static_fields_),   "shadow$_num_reference_static_fields_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, object_size_),                   "shadow$_object_size_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, primitive_type_),                "shadow$_primitive_type_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, reference_instance_offsets_),    "shadow$_reference_instance_offsets_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, reference_static_offsets_),      "shadow$_reference_static_offsets_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, iftable_),                       "shadow$_iftable_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, source_file_),                   "shadow$_source_file_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, status_),                        "shadow$_status_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, clinit_thread_id_),              "shadow$_clinit_thread_id_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, super_class_type_idx_),          "shadow$_super_class_type_idx_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, class_size_),                    "shadow$_class_size_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, array_rank_),                    "shadow$_array_rank_"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Class, access_flags_),                  "shadow$_access_flags_"));
+  };
+};
+
+struct StringOffsets : public CheckOffsets {
+  StringOffsets() {
+    s = sizeof(String);
+    c = "Ljava/lang/String;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(String, array_),     "value"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(String, hash_code_), "hashCode"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(String, offset_),    "offset"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(String, count_),     "count"));
+  };
+};
+
+struct ThrowableOffsets : public CheckOffsets {
+  ThrowableOffsets() {
+    s = sizeof(Throwable);
+    c = "Ljava/lang/Throwable;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Throwable, cause_),                 "cause"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Throwable, detail_message_),        "detailMessage"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Throwable, stack_state_),           "stackState"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Throwable, stack_trace_),           "stackTrace"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(Throwable, suppressed_exceptions_), "suppressedExceptions"));
+  };
+};
+
+struct StackTraceElementOffsets : public CheckOffsets {
+  StackTraceElementOffsets() {
+    s = sizeof(StackTraceElement);
+    c = "Ljava/lang/StackTraceElement;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(StackTraceElement, declaring_class_), "declaringClass"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(StackTraceElement, file_name_),       "fileName"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(StackTraceElement, method_name_),     "methodName"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(StackTraceElement, line_number_),     "lineNumber"));
+  };
+};
+
+struct ClassLoaderOffsets : public CheckOffsets {
+  ClassLoaderOffsets() {
+    s = sizeof(ClassLoader);
+    c = "Ljava/lang/ClassLoader;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(ClassLoader, packages_), "packages"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(ClassLoader, parent_),   "parent"));
+  };
+};
+
+struct BaseDexClassLoaderOffsets : public CheckOffsets {
+  BaseDexClassLoaderOffsets() {
+    s = sizeof(BaseDexClassLoader);
+    c = "Ldalvik/system/BaseDexClassLoader;";
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(BaseDexClassLoader, original_path_), "originalPath"));
+    o.push_back(CheckOffset(OFFSETOF_MEMBER(BaseDexClassLoader, path_list_),   "pathList"));
+  };
+};
+
+struct PathClassLoaderOffsets : public CheckOffsets {
+  PathClassLoaderOffsets() {
+    s = sizeof(PathClassLoader);
+    c = "Ldalvik/system/PathClassLoader;";
+  };
+};
+
 // C++ fields must exactly match the fields in the Java classes. If this fails,
 // reorder the fields in the C++ class. Managed class fields are ordered by
-// ClassLinker::LinkInstanceFields.
+// ClassLinker::LinkFields.
 TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
-  Class* string = class_linker_->FindSystemClass( "Ljava/lang/String;");
-  ASSERT_EQ(4U, string->NumInstanceFields());
-  EXPECT_TRUE(string->GetInstanceField(0)->GetName()->Equals("value"));
-  EXPECT_TRUE(string->GetInstanceField(1)->GetName()->Equals("hashCode"));
-  EXPECT_TRUE(string->GetInstanceField(2)->GetName()->Equals("offset"));
-  EXPECT_TRUE(string->GetInstanceField(3)->GetName()->Equals("count"));
-
-  Class* throwable = class_linker_->FindSystemClass( "Ljava/lang/Throwable;");
-  ASSERT_EQ(5U, throwable->NumInstanceFields());
-  EXPECT_TRUE(throwable->GetInstanceField(0)->GetName()->Equals("cause"));
-  EXPECT_TRUE(throwable->GetInstanceField(1)->GetName()->Equals("detailMessage"));
-  EXPECT_TRUE(throwable->GetInstanceField(2)->GetName()->Equals("stackState"));
-  EXPECT_TRUE(throwable->GetInstanceField(3)->GetName()->Equals("stackTrace"));
-  EXPECT_TRUE(throwable->GetInstanceField(4)->GetName()->Equals("suppressedExceptions"));
-
-  Class* stack_trace_element = class_linker_->FindSystemClass( "Ljava/lang/StackTraceElement;");
-  ASSERT_EQ(4U, stack_trace_element->NumInstanceFields());
-  EXPECT_TRUE(stack_trace_element->GetInstanceField(0)->GetName()->Equals("declaringClass"));
-  EXPECT_TRUE(stack_trace_element->GetInstanceField(1)->GetName()->Equals("fileName"));
-  EXPECT_TRUE(stack_trace_element->GetInstanceField(2)->GetName()->Equals("methodName"));
-  EXPECT_TRUE(stack_trace_element->GetInstanceField(3)->GetName()->Equals("lineNumber"));
-
-  Class* accessible_object = class_linker_->FindSystemClass("Ljava/lang/reflect/AccessibleObject;");
-  ASSERT_EQ(1U, accessible_object->NumInstanceFields());
-  EXPECT_TRUE(accessible_object->GetInstanceField(0)->GetName()->Equals("flag"));
-
-  Class* field = class_linker_->FindSystemClass("Ljava/lang/reflect/Field;");
-  ASSERT_EQ(6U, field->NumInstanceFields());
-  EXPECT_TRUE(field->GetInstanceField(0)->GetName()->Equals("declaringClass"));
-  EXPECT_TRUE(field->GetInstanceField(1)->GetName()->Equals("genericType"));
-  EXPECT_TRUE(field->GetInstanceField(2)->GetName()->Equals("type"));
-  EXPECT_TRUE(field->GetInstanceField(3)->GetName()->Equals("name"));
-  EXPECT_TRUE(field->GetInstanceField(4)->GetName()->Equals("slot"));
-  EXPECT_TRUE(field->GetInstanceField(5)->GetName()->Equals("genericTypesAreInitialized"));
-
-  Class* method = class_linker_->FindSystemClass("Ljava/lang/reflect/Method;");
-  ASSERT_EQ(11U, method->NumInstanceFields());
-  EXPECT_TRUE(method->GetInstanceField( 0)->GetName()->Equals("declaringClass"));
-  EXPECT_TRUE(method->GetInstanceField( 1)->GetName()->Equals("exceptionTypes"));
-  EXPECT_TRUE(method->GetInstanceField( 2)->GetName()->Equals("formalTypeParameters"));
-  EXPECT_TRUE(method->GetInstanceField( 3)->GetName()->Equals("genericExceptionTypes"));
-  EXPECT_TRUE(method->GetInstanceField( 4)->GetName()->Equals("genericParameterTypes"));
-  EXPECT_TRUE(method->GetInstanceField( 5)->GetName()->Equals("genericReturnType"));
-  EXPECT_TRUE(method->GetInstanceField( 6)->GetName()->Equals("returnType"));
-  EXPECT_TRUE(method->GetInstanceField( 7)->GetName()->Equals("name"));
-  EXPECT_TRUE(method->GetInstanceField( 8)->GetName()->Equals("parameterTypes"));
-  EXPECT_TRUE(method->GetInstanceField( 9)->GetName()->Equals("genericTypesAreInitialized"));
-  EXPECT_TRUE(method->GetInstanceField(10)->GetName()->Equals("slot"));
-
-  Class* class_loader = class_linker_->FindSystemClass("Ljava/lang/ClassLoader;");
-  ASSERT_EQ(2U, class_loader->NumInstanceFields());
-  EXPECT_TRUE(class_loader->GetInstanceField(0)->GetName()->Equals("packages"));
-  EXPECT_TRUE(class_loader->GetInstanceField(1)->GetName()->Equals("parent"));
-
-  Class* dex_base_class_loader = class_linker_->FindSystemClass("Ldalvik/system/BaseDexClassLoader;");
-  ASSERT_EQ(2U, dex_base_class_loader->NumInstanceFields());
-  EXPECT_TRUE(dex_base_class_loader->GetInstanceField(0)->GetName()->Equals("originalPath"));
-  EXPECT_TRUE(dex_base_class_loader->GetInstanceField(1)->GetName()->Equals("pathList"));
+  EXPECT_TRUE(ObjectOffsets().Check());
+  EXPECT_TRUE(AccessibleObjectOffsets().Check());
+  EXPECT_TRUE(FieldOffsets().Check());
+  EXPECT_TRUE(MethodOffsets().Check());
+  EXPECT_TRUE(ClassOffsets().Check());
+  EXPECT_TRUE(StringOffsets().Check());
+  EXPECT_TRUE(ThrowableOffsets().Check());
+  EXPECT_TRUE(StackTraceElementOffsets().Check());
+  EXPECT_TRUE(ClassLoaderOffsets().Check());
+  EXPECT_TRUE(BaseDexClassLoaderOffsets().Check());
+  EXPECT_TRUE(PathClassLoaderOffsets().Check());
 }
 
 // The first reference array element must be a multiple of 8 bytes from the
diff --git a/src/class_loader.h b/src/class_loader.h
index ff62d12..80435c6 100644
--- a/src/class_loader.h
+++ b/src/class_loader.h
@@ -29,6 +29,7 @@
   // TODO: remove once we can create a real PathClassLoader
   std::vector<const DexFile*> class_path_;
 
+  friend struct ClassLoaderOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader);
 };
 
@@ -38,6 +39,8 @@
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   String* original_path_;
   Object* path_list_;
+
+  friend struct BaseDexClassLoaderOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(BaseDexClassLoader);
 };
 
@@ -49,6 +52,7 @@
   static void ResetClass();
  private:
   static Class* dalvik_system_PathClassLoader_;
+  friend struct PathClassLoaderOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(PathClassLoader);
 };
 
diff --git a/src/heap.h b/src/heap.h
index 4922207..3dc612a 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -134,13 +134,14 @@
     verify_object_disabled_ = true;
   }
 
+  static void RecordFree(Space* space, const Object* object);
+
  private:
   // Allocates uninitialized storage.
   static Object* Allocate(size_t num_bytes);
   static Object* Allocate(Space* space, size_t num_bytes);
 
   static void RecordAllocation(Space* space, const Object* object);
-  static void RecordFree(Space* space, const Object* object);
   static void RecordImageAllocations(Space* space);
 
   static void CollectGarbageInternal();
diff --git a/src/heap_test.cc b/src/heap_test.cc
index 53489e4..2a4cbbf 100644
--- a/src/heap_test.cc
+++ b/src/heap_test.cc
@@ -6,7 +6,7 @@
 
 class HeapTest : public CommonTest {};
 
-TEST_F(HeapTest, DISABLED_GarbageCollectClassLinkerInit) {
+TEST_F(HeapTest, GarbageCollectClassLinkerInit) {
   // garbage is created during ClassLinker::Init
   Heap::CollectGarbage();
 }
diff --git a/src/image_test.cc b/src/image_test.cc
index f07588a..0bd79db 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -16,14 +16,13 @@
 class ImageTest : public CommonTest {};
 
 TEST_F(ImageTest, WriteRead) {
-  // TODO: move the touching of classes and GC to the ImageWriter proper
+  // TODO: remove the touching of classes, call Compiler instead
   for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) {
     const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i);
     const char* descriptor = java_lang_dex_file_->GetClassDescriptor(class_def);
     Class* klass = class_linker_->FindSystemClass(descriptor);
     ASSERT_TRUE(klass != NULL) << descriptor;
   }
-  // TODO: Heap::CollectGarbage before writing
 
   ImageWriter writer;
   ScratchFile tmp;
diff --git a/src/image_writer.cc b/src/image_writer.cc
index a49b261..859da86 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -35,6 +35,7 @@
   if (!Init()) {
     return false;
   }
+  Heap::CollectGarbage();
   CalculateNewObjectOffsets();
   CopyAndFixupObjects();
 
@@ -173,10 +174,6 @@
   // TODO: special case init of pointers to malloc data (or removal of these pointers)
   if (orig->IsClass()) {
     FixupClass(orig->AsClass(), down_cast<Class*>(copy));
-  } else if (orig->IsMethod()) {
-    FixupMethod(orig->AsMethod(), down_cast<Method*>(copy));
-  } else if (orig->IsField()) {
-    FixupField(orig->AsField(), down_cast<Field*>(copy));
   } else if (orig->IsObjectArray()) {
     FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
   } else {
@@ -186,22 +183,6 @@
 
 void ImageWriter::FixupClass(const Class* orig, Class* copy) {
   FixupInstanceFields(orig, copy);
-  copy->descriptor_ = down_cast<String*>(GetImageAddress(orig->descriptor_));
-  copy->dex_cache_ = down_cast<DexCache*>(GetImageAddress(orig->dex_cache_));
-  copy->verify_error_class_ = down_cast<Class*>(GetImageAddress(orig->verify_error_class_));
-  copy->component_type_ = down_cast<Class*>(GetImageAddress(orig->component_type_));
-  copy->super_class_ = down_cast<Class*>(GetImageAddress(orig->super_class_));
-  copy->class_loader_ = down_cast<ClassLoader*>(GetImageAddress(orig->class_loader_));
-  copy->interfaces_ = down_cast<ObjectArray<Class>*>(GetImageAddress(orig->interfaces_));
-  copy->direct_methods_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->direct_methods_));
-  copy->virtual_methods_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->virtual_methods_));
-  copy->vtable_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->vtable_));
-  // TODO: convert iftable_ to heap allocated storage
-  // TODO: convert ifvi_pool_ to heap allocated storage
-  copy->ifields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->ifields_));
-  // TODO: convert source_file_ to heap allocated storage
-  copy->sfields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->sfields_));
-  copy->interfaces_type_idx_ = down_cast<IntArray*>(GetImageAddress(orig->interfaces_type_idx_));
   FixupStaticFields(orig, copy);
 }
 
@@ -218,30 +199,13 @@
   return copy_code;
 }
 
-// TODO: remove this slow path
 void ImageWriter::FixupMethod(const Method* orig, Method* copy) {
   FixupInstanceFields(orig, copy);
-  // TODO: remove need for this by adding "signature" to java.lang.reflect.Method
-  copy->signature_ = down_cast<String*>(GetImageAddress(orig->signature_));
-  DCHECK(copy->signature_ != NULL);
   // TODO: convert shorty_ to heap allocated storage
-  copy->dex_cache_strings_ = down_cast<ObjectArray<String>*>(GetImageAddress(orig->dex_cache_strings_));
-  copy->dex_cache_resolved_types_ = down_cast<ObjectArray<Class>*>(GetImageAddress(orig->dex_cache_resolved_types_));
-  copy->dex_cache_resolved_methods_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->dex_cache_resolved_methods_));
-  copy->dex_cache_resolved_fields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->dex_cache_resolved_fields_));
-  copy->dex_cache_code_and_direct_methods_ = down_cast<CodeAndDirectMethods*>(GetImageAddress(orig->dex_cache_code_and_direct_methods_));
-  copy->dex_cache_initialized_static_storage_ = down_cast<ObjectArray<StaticStorageBase>*>(GetImageAddress(orig->dex_cache_initialized_static_storage_));
-  copy->code_array_ = down_cast<ByteArray*>(GetImageAddress(orig->code_array_));
   copy->code_ = FixupCode(copy->code_array_, orig->code_);
-  copy->invoke_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig->invoke_stub_array_));
   copy->invoke_stub_ = reinterpret_cast<Method::InvokeStub*>(FixupCode(copy->invoke_stub_array_, reinterpret_cast<void*>(orig->invoke_stub_)));
 }
 
-void ImageWriter::FixupField(const Field* orig, Field* copy) {
-  FixupInstanceFields(orig, copy);
-  // TODO: convert descriptor_ to heap allocated storage
-}
-
 void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
   for (int32_t i = 0; i < orig->GetLength(); ++i) {
     const Object* element = orig->Get(i);
diff --git a/src/image_writer.h b/src/image_writer.h
index 3352adb..9dac31a 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -75,7 +75,6 @@
   static void CopyAndFixupObjectsCallback(Object* obj, void *arg);
   void FixupClass(const Class* orig, Class* copy);
   void FixupMethod(const Method* orig, Method* copy);
-  void FixupField(const Field* orig, Field* copy);
   void FixupObject(const Object* orig, Object* copy);
   void FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy);
   void FixupInstanceFields(const Object* orig, Object* copy);
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index a2f1a56..b3d21a3 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -6,6 +6,7 @@
 #include <vector>
 
 #include "class_loader.h"
+#include "dex_cache.h"
 #include "heap.h"
 #include "indirect_reference_table.h"
 #include "intern_table.h"
@@ -148,6 +149,7 @@
   Space* space = static_cast<Space*>(arg);
   for (size_t i = 0; i < num_ptrs; ++i) {
     Object* obj = static_cast<Object*>(ptrs[i]);
+    Heap::RecordFree(space, obj);
     space->Free(obj);
   }
   // TODO, unlock heap if concurrent
@@ -219,13 +221,6 @@
   }
 }
 
-void MarkSweep::ScanInterfaces(const Class* klass) {
-  DCHECK(klass != NULL);
-  for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
-    MarkObject(klass->GetInterface(i));
-  }
-}
-
 // Scans the header, static field references, and interface pointers
 // of a class object.
 void MarkSweep::ScanClass(const Object* obj) {
@@ -233,6 +228,10 @@
   DCHECK(obj->IsClass());
   const Class* klass = obj->AsClass();
   MarkObject(klass->GetClass());
+  ScanInstanceFields(obj);
+  MarkObject(klass->GetDescriptor());
+  MarkObject(klass->GetDexCache());
+  MarkObject(klass->GetVerifyErrorClass());
   if (klass->IsArrayClass()) {
     MarkObject(klass->GetComponentType());
   }
@@ -240,13 +239,14 @@
     MarkObject(klass->GetSuperClass());
   }
   MarkObject(klass->GetClassLoader());
-  ScanInstanceFields(obj);
-  ScanStaticFields(klass);
-  // TODO: scan methods
-  // TODO: scan instance fields
   if (klass->IsLoaded()) {
-    ScanInterfaces(klass);
+    MarkObject(klass->GetInterfaces());
+    MarkObject(klass->GetDirectMethods());
+    MarkObject(klass->GetVirtualMethods());
+    MarkObject(klass->GetIFields());
+    MarkObject(klass->GetSFields());
   }
+  ScanStaticFields(klass);
 }
 
 // Scans the header of all array objects.  If the array object is
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index 841d819..fe37cab 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -82,9 +82,6 @@
   // Used by ScanInstanceFields and ScanStaticFields
   void ScanFields(const Object* obj, uint32_t ref_offsets, bool is_static);
 
-  // Grays interface class objects.
-  void ScanInterfaces(const Class* klass);
-
   // Grays references in an array.
   void ScanArray(const Object* obj);
 
diff --git a/src/object.h b/src/object.h
index 23ce3c4..9e5cf2d 100644
--- a/src/object.h
+++ b/src/object.h
@@ -140,7 +140,6 @@
  * fields followed by 2 ref instance fields.]
  */
 #define CLASS_WALK_SUPER ((unsigned int)(3))
-#define CLASS_SMALLEST_OFFSET (sizeof(struct Object))
 #define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8)
 #define CLASS_OFFSET_ALIGNMENT 4
 #define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1))
@@ -149,7 +148,7 @@
  * Local use only.
  */
 #define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \
-    (((unsigned int)(byteOffset) - CLASS_SMALLEST_OFFSET) / \
+    ((unsigned int)(byteOffset) / \
      CLASS_OFFSET_ALIGNMENT)
 /*
  * Is the given offset too large to be encoded?
@@ -166,8 +165,7 @@
  * Return an offset, given a bit number as returned from CLZ.
  */
 #define CLASS_OFFSET_FROM_CLZ(rshift) \
-    MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT) + \
-                 CLASS_SMALLEST_OFFSET)
+    MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT))
 
 #define OFFSET_OF_OBJECT_MEMBER(type, field) \
     MemberOffset(OFFSETOF_MEMBER(type, field))
@@ -444,6 +442,7 @@
 
   Monitor* monitor_;
 
+  friend struct ObjectOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
 };
 
@@ -480,6 +479,8 @@
  private:
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   uint32_t java_flag_;  // can accessibility checks be bypassed
+  friend struct AccessibleObjectOffsets;  // for verifying offset information
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AccessibleObject);
 };
 
 // C++ mirror of java.lang.reflect.Field
@@ -584,24 +585,32 @@
   void SetObj(Object* object, const Object* new_value) const;
 
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
+
   // The class in which this field is declared.
   Class* declaring_class_;
+
   Object* generic_type_;
-  uint32_t generic_types_are_initialized_;
-  const String* name_;
-  // Offset of field within an instance or in the Class' static fields
-  uint32_t offset_;
+
   // Type of the field
-  // TODO: unused by ART (which uses the type_idx below), remove
   Class* type_;
 
-  // TODO: expose these fields in the Java version of this Object
+  const String* name_;
+
   uint32_t access_flags_;
+
+  // Offset of field within an instance or in the Class' static fields
+  uint32_t offset_;
+
   // Dex cache index of resolved type
   uint32_t type_idx_;
 
+  int32_t slot_;
+
+  uint32_t generic_types_are_initialized_;
+
   static Class* java_lang_reflect_Field_;
 
+  friend struct FieldOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Field);
 };
 
@@ -978,10 +987,6 @@
  private:
   uint32_t GetReturnTypeIdx() const;
 
-  // TODO: the image writer should know the offsets of these fields as they
-  // should appear in the libcore Java mirror
-  friend class ImageWriter;
-
   // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
   // the class we are a part of
   Class* declaring_class_;
@@ -990,38 +995,6 @@
   Object* java_generic_exception_types_;
   Object* java_generic_parameter_types_;
   Object* java_generic_return_type_;
-  Class* java_return_type_;  // Unused by ART
-  String* name_;
-  ObjectArray<Class>* java_parameter_types_;
-  uint32_t java_generic_types_are_initialized_;
-  uint32_t java_slot_;
-
-  // TODO: start of non-Java mirror fields, place these in the Java piece
-
-  // access flags; low 16 bits are defined by spec (could be uint16_t?)
-  uint32_t access_flags_;
-
-  // For concrete virtual methods, this is the offset of the method
-  // in Class::vtable_.
-  //
-  // For abstract methods in an interface class, this is the offset
-  // of the method in "iftable_[n]->method_index_array_".
-  uint16_t method_index_;
-
-  // Method bounds; not needed for an abstract method.
-  //
-  // For a native method, we compute the size of the argument list, and
-  // set "insSize" and "registerSize" equal to it.
-  uint16_t num_registers_;  // ins + locals
-  uint16_t num_outs_;
-  uint16_t num_ins_;
-
-  // Total size in bytes of the frame
-  size_t frame_size_in_bytes_;
-
-  // Architecture-dependent register spill masks
-  uint32_t core_spill_mask_;
-  uint32_t fp_spill_mask_;
 
   // The method descriptor.  This represents the parameters a method
   // takes and value it returns.  This string is a list of the type
@@ -1035,52 +1008,99 @@
   //   (IDLjava/lang/Thread;)Ljava/lang/Object;
   String* signature_;
 
-  // Method prototype descriptor string (return and argument types).
-  uint32_t proto_idx_;
+  String* name_;
+
+  ObjectArray<Class>* java_parameter_types_;
+
+  Class* java_return_type_;  // Unused by ART
+
+  // Storage for mapping_table_
+  const ByteArray* mapping_table_;
+
+  // Storage for invoke_stub_
+  const ByteArray* invoke_stub_array_;
+
+  // Storage for code_
+  const ByteArray* code_array_;
+
+  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
+  ObjectArray<String>* dex_cache_strings_;
+
+  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
+  ObjectArray<Class>* dex_cache_resolved_types_;
+
+  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
+  CodeAndDirectMethods* dex_cache_code_and_direct_methods_;
+
+  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
+  ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_;
+
+  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
+  ObjectArray<Field>* dex_cache_resolved_fields_;
+
+  // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
+  ObjectArray<Method>* dex_cache_resolved_methods_;
+
+  // Architecture-dependent register spill mask
+  uint32_t core_spill_mask_;
 
   // Offset to the CodeItem.
   uint32_t code_item_offset_;
 
-  // Index of the return type
-  uint32_t java_return_type_idx_;
+  // Architecture-dependent register spill mask
+  uint32_t fp_spill_mask_;
 
-  // The short-form method descriptor string. TODO: make String*
-  const char* shorty_;
+  // Total size in bytes of the frame
+  size_t frame_size_in_bytes_;
 
-  // short cuts to declaring_class_->dex_cache_ members for fast compiled code
-  // access
-  ObjectArray<String>* dex_cache_strings_;
-  ObjectArray<Class>* dex_cache_resolved_types_;
-  ObjectArray<Method>* dex_cache_resolved_methods_;
-  ObjectArray<Field>* dex_cache_resolved_fields_;
-  CodeAndDirectMethods* dex_cache_code_and_direct_methods_;
-  ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_;
-
- private:
-  // Storage for code_
-  const ByteArray* code_array_;
-
-  // Storage for mapping_table_
-  const ByteArray* mapping_table_;
+  // Native invocation stub entry point for calling from native to managed code.
+  const InvokeStub* invoke_stub_;
 
   // Compiled code associated with this method for callers from managed code.
   // May be compiled managed code or a bridge for invoking a native method.
   const void* code_;
 
-  // Offset of return PC within frame for compiled code (in bytes)
-  size_t return_pc_offset_in_bytes_;
+  // Index of the return type
+  uint32_t java_return_type_idx_;
+
+  // access flags; low 16 bits are defined by spec (could be uint16_t?)
+  uint32_t access_flags_;
+
+  // For concrete virtual methods, this is the offset of the method
+  // in Class::vtable_.
+  //
+  // For abstract methods in an interface class, this is the offset
+  // of the method in "iftable_[n]->method_index_array_".
+  uint32_t method_index_;  // (could be uint16_t)
 
   // The target native method registered with this method
   const void* native_method_;
 
-  // Storage for invoke_stub_
-  const ByteArray* invoke_stub_array_;
+  // Method bounds; not needed for an abstract method.
+  //
+  // For a native method, we compute the size of the argument list, and
+  // set "insSize" and "registerSize" equal to it.
+  uint32_t num_ins_;  // (could be uint16_t)
+  uint32_t num_outs_;  // (could be uint16_t)
+  uint32_t num_registers_;  // ins + locals  // (could be uint16_t)
 
-  // Native invocation stub entry point for calling from native to managed code.
-  const InvokeStub* invoke_stub_;
+  // Method prototype descriptor string (return and argument types).
+  uint32_t proto_idx_;
+
+  // Offset of return PC within frame for compiled code (in bytes)
+  size_t return_pc_offset_in_bytes_;
+
+  // The short-form method descriptor string. TODO: make String*
+  const char* shorty_;
+
+  uint32_t java_generic_types_are_initialized_;
+
+  uint32_t java_slot_;
 
   static Class* java_lang_reflect_Method_;
 
+  friend class ImageWriter;  // for relocating code_ and invoke_stub_
+  friend struct MethodOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Method);
 };
 
@@ -1928,7 +1948,7 @@
   }
 
   Class* GetVerifyErrorClass() const {
-    DCHECK(IsErroneous());
+    // DCHECK(IsErroneous());
     return GetFieldObject<Class*>(
         OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false);
   }
@@ -1955,76 +1975,100 @@
   bool IsAssignableFromArray(const Class* klass) const;
   bool IsSubClass(const Class* klass) const;
 
-  // TODO: the image writer should know the offsets of these fields as they
-  // should appear in the libcore Java mirror
-  friend class ImageWriter;
-
   // descriptor for the class such as "java.lang.Class" or "[C"
   String* name_;  // TODO initialize
 
-  // descriptor for the class such as "Ljava/lang/Class;" or "[C"
-  String* descriptor_;
+  // Virtual method table (vtable), for use by "invoke-virtual".  The
+  // vtable from the superclass is copied in, and virtual methods from
+  // our class either replace those from the super or are appended.
+  ObjectArray<Method>* vtable_;
 
-  // access flags; low 16 bits are defined by VM spec
-  uint32_t access_flags_;  // TODO: make an instance field?
+  // virtual methods defined in this class; invoked through vtable
+  ObjectArray<Method>* virtual_methods_;
 
-  // DexCache of resolved constant pool entries
-  // (will be NULL for VM-generated, e.g. arrays and primitive classes)
-  DexCache* dex_cache_;
-
-  // state of class initialization
-  Status status_;
+  // defining class loader, or NULL for the "bootstrap" system loader
+  const ClassLoader* class_loader_;  // TODO: make an instance field
 
   // If class verify fails, we must return same error on subsequent tries.
   // Update with SetVerifyErrorClass to ensure a write barrier is used.
   const Class* verify_error_class_;
 
-  // threadId, used to check for recursive <clinit> invocation
-  pid_t clinit_thread_id_;
-
-  // Total object size; used when allocating storage on gc heap.  (For
-  // interfaces and abstract classes this will be zero.)
-  size_t object_size_;
+  // The superclass, or NULL if this is java.lang.Object or a
+  // primitive type.
+  // see also super_class_type_idx_;
+  Class* super_class_;
 
   // For array classes, the class object for base element, for
   // instanceof/checkcast (for String[][][], this will be String).
   // Otherwise, NULL.
   Class* component_type_;  // TODO: make an instance field
 
-  // For array classes, the number of array dimensions, e.g. int[][]
-  // is 2.  Otherwise 0.
-  int32_t array_rank_;
+  // descriptor for the class such as "Ljava/lang/Class;" or "[C"
+  String* descriptor_;
 
-  // primitive type index, or kPrimNot (0); set for generated prim classes
-  PrimitiveType primitive_type_;
-
-  // The superclass, or NULL if this is java.lang.Object or a
-  // primitive type.
-  Class* super_class_;  // TODO: make an instance field
-  uint32_t super_class_type_idx_;
-
-  // defining class loader, or NULL for the "bootstrap" system loader
-  const ClassLoader* class_loader_;  // TODO: make an instance field
-
-  // initiating class loader list
-  // NOTE: for classes with low serialNumber, these are unused, and the
-  // values are kept in a table in gDvm.
-  // InitiatingLoaderList initiating_loader_list_;
-
-  // array of interfaces this class implements directly
-  ObjectArray<Class>* interfaces_;
-  IntArray* interfaces_type_idx_;
+  // DexCache of resolved constant pool entries
+  // (will be NULL for VM-generated, e.g. arrays and primitive classes)
+  DexCache* dex_cache_;
 
   // static, private, and <init> methods
   ObjectArray<Method>* direct_methods_;
 
-  // virtual methods defined in this class; invoked through vtable
-  ObjectArray<Method>* virtual_methods_;
+  // instance fields
+  //
+  // These describe the layout of the contents of an Object.
+  // Note that only the fields directly declared by this class are
+  // listed in ifields; fields declared by a superclass are listed in
+  // the superclass's Class.ifields.
+  //
+  // All instance fields that refer to objects are guaranteed to be at
+  // the beginning of the field list.  num_reference_instance_fields_
+  // specifies the number of reference fields.
+  ObjectArray<Field>* ifields_;
 
-  // Virtual method table (vtable), for use by "invoke-virtual".  The
-  // vtable from the superclass is copied in, and virtual methods from
-  // our class either replace those from the super or are appended.
-  ObjectArray<Method>* vtable_;
+  // Static fields
+  ObjectArray<Field>* sfields_;
+
+  // array of type_idx's for interfaces this class implements directly
+  // see also interfaces_
+  IntArray* interfaces_type_idx_;
+
+  // array of interfaces this class implements directly
+  // see also interfaces_type_idx_
+  ObjectArray<Class>* interfaces_;
+
+  // size of ifvi_pool_
+  size_t ifvi_pool_count_;
+
+  // The interface vtable indices for iftable get stored here.  By
+  // placing them all in a single pool for each class that implements
+  // interfaces, we decrease the number of allocations.
+  //
+  // see also ifvi_pool_count_
+  //
+  // TODO convert to IntArray
+  uint32_t* ifvi_pool_;
+
+  // size of iftable_
+  size_t iftable_count_;
+
+  // number of instance fields that are object refs
+  size_t num_reference_instance_fields_;
+
+  // number of static fields that are object refs
+  size_t num_reference_static_fields_;
+
+  // Total object size; used when allocating storage on gc heap.
+  // (For interfaces and abstract classes this will be zero.)
+  size_t object_size_;
+
+  // primitive type index, or kPrimNot (0); set for generated prim classes
+  PrimitiveType primitive_type_;
+
+  // Bitmap of offsets of ifields.
+  uint32_t reference_instance_offsets_;
+
+  // Bitmap of offsets of sfields.
+  uint32_t reference_static_offsets_;
 
   // Interface table (iftable_), one entry per interface supported by
   // this class.  That means one entry for each interface we support
@@ -2039,54 +2083,45 @@
   //
   // For every interface a concrete class implements, we create a list
   // of virtualMethod indices for the methods in the interface.
-  size_t iftable_count_;
+  //
+  // see also iftable_count_;
   // TODO convert to ObjectArray<?>
+  //
   InterfaceEntry* iftable_;
 
-  // The interface vtable indices for iftable get stored here.  By
-  // placing them all in a single pool for each class that implements
-  // interfaces, we decrease the number of allocations.
-  size_t ifvi_pool_count_;
-  // TODO convert to IntArray
-  uint32_t* ifvi_pool_;
-
-  // instance fields
-  //
-  // These describe the layout of the contents of a
-  // DataObject-compatible Object.  Note that only the fields directly
-  // declared by this class are listed in ifields; fields declared by
-  // a superclass are listed in the superclass's Class.ifields.
-  //
-  // All instance fields that refer to objects are guaranteed to be at
-  // the beginning of the field list.  num_reference_instance_fields_
-  // specifies the number of reference fields.
-  ObjectArray<Field>* ifields_;
-
-  // number of instance fields that are object refs
-  size_t num_reference_instance_fields_;
-
-  // Bitmap of offsets of ifields.
-  uint32_t reference_instance_offsets_;
-
   // source file name, if known.  Otherwise, NULL.
   const char* source_file_;
 
-  // Static fields
-  ObjectArray<Field>* sfields_;
+  // state of class initialization
+  Status status_;
 
-  // number of static fields that are object refs
-  size_t num_reference_static_fields_;
+  // threadId, used to check for recursive <clinit> invocation
+  uint32_t clinit_thread_id_;
 
-  // Bitmap of offsets of sfields.
-  uint32_t reference_static_offsets_;
+  // Set in LoadClass, used to LinkClass
+  // see also super_class_
+  uint32_t super_class_type_idx_;
 
   // Total class size; used when allocating storage on gc heap.
   size_t class_size_;
 
+  // For array classes, the number of array dimensions, e.g. int[][]
+  // is 2.  Otherwise 0.
+  int32_t array_rank_;
+
+  // access flags; low 16 bits are defined by VM spec
+  uint32_t access_flags_;
+
+  // TODO: ?
+  // initiating class loader list
+  // NOTE: for classes with low serialNumber, these are unused, and the
+  // values are kept in a table in gDvm.
+  // InitiatingLoaderList initiating_loader_list_;
+
   // Location of first static field.
   uint32_t fields_[0];
 
- private:
+  friend struct ClassOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
 };
 
@@ -2171,8 +2206,7 @@
 
 inline void Field::SetOffset(MemberOffset num_bytes) {
   DCHECK(GetDeclaringClass()->IsLoaded());
-  DCHECK_LE(CLASS_SMALLEST_OFFSET, num_bytes.Uint32Value());
- Class* type = GetTypeDuringLinking();
+  Class* type = GetTypeDuringLinking();
   if (type != NULL && (type->IsPrimitiveDouble() || type->IsPrimitiveLong())) {
     DCHECK(IsAligned(num_bytes.Uint32Value(), 8));
   }
@@ -2333,14 +2367,6 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodClass);
 };
 
-class DataObject : public Object {
- public:
-  // Location of first instance field.
-  uint32_t fields_[0];
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(DataObject);
-};
-
 template<class T>
 class PrimitiveArray : public Array {
  public:
@@ -2500,6 +2526,7 @@
 
   static Class* java_lang_String_;
 
+  friend struct StringOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(String);
 };
 
@@ -2583,6 +2610,7 @@
 }
 
 inline void Class::SetDescriptor(String* new_descriptor) {
+  DCHECK(GetDescriptor() == NULL);
   DCHECK(new_descriptor != NULL);
   DCHECK_NE(0, new_descriptor->GetLength());
   SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, descriptor_),
@@ -2635,6 +2663,7 @@
   Object* stack_trace_;
   Object* suppressed_exceptions_;
 
+  friend struct ThrowableOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable);
 };
 
@@ -2683,6 +2712,8 @@
   }
 
   static Class* java_lang_StackTraceElement_;
+
+  friend struct StackTraceElementOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement);
 };