Move ArtFields and ArtMethods to be a length prefixed array

Fixes race conditions between changing method and fields arrays
being seen in the wrong order by the GC.

Bug: 22832610
Change-Id: Ia21d6698f73ba207a6392c3d6b9be2658933073f
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 195b3b3..e6710ed 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -2063,37 +2063,34 @@
   // Play with it...
 
   // Static fields.
-  ArtField* fields = c->GetSFields();
-  size_t num_fields = c->NumStaticFields();
-  for (size_t i = 0; i < num_fields; ++i) {
-    ArtField* f = &fields[i];
-    Primitive::Type type = f->GetTypeAsPrimitiveType();
+  for (ArtField& f : c->GetSFields()) {
+    Primitive::Type type = f.GetTypeAsPrimitiveType();
     if (test_type != type) {
      continue;
     }
     switch (type) {
       case Primitive::Type::kPrimBoolean:
-        GetSetBooleanStatic(f, self, m, test);
+        GetSetBooleanStatic(&f, self, m, test);
         break;
       case Primitive::Type::kPrimByte:
-        GetSetByteStatic(f, self, m, test);
+        GetSetByteStatic(&f, self, m, test);
         break;
       case Primitive::Type::kPrimChar:
-        GetSetCharStatic(f, self, m, test);
+        GetSetCharStatic(&f, self, m, test);
         break;
       case Primitive::Type::kPrimShort:
-        GetSetShortStatic(f, self, m, test);
+        GetSetShortStatic(&f, self, m, test);
         break;
       case Primitive::Type::kPrimInt:
-        GetSet32Static(f, self, m, test);
+        GetSet32Static(&f, self, m, test);
         break;
       case Primitive::Type::kPrimLong:
-        GetSet64Static(f, self, m, test);
+        GetSet64Static(&f, self, m, test);
         break;
       case Primitive::Type::kPrimNot:
         // Don't try array.
-        if (f->GetTypeDescriptor()[0] != '[') {
-          GetSetObjStatic(f, self, m, test);
+        if (f.GetTypeDescriptor()[0] != '[') {
+          GetSetObjStatic(&f, self, m, test);
         }
         break;
       default:
@@ -2102,37 +2099,34 @@
   }
 
   // Instance fields.
-  fields = c->GetIFields();
-  num_fields = c->NumInstanceFields();
-  for (size_t i = 0; i < num_fields; ++i) {
-    ArtField* f = &fields[i];
-    Primitive::Type type = f->GetTypeAsPrimitiveType();
+  for (ArtField& f : c->GetIFields()) {
+    Primitive::Type type = f.GetTypeAsPrimitiveType();
     if (test_type != type) {
       continue;
     }
     switch (type) {
       case Primitive::Type::kPrimBoolean:
-        GetSetBooleanInstance(&obj, f, self, m, test);
+        GetSetBooleanInstance(&obj, &f, self, m, test);
         break;
       case Primitive::Type::kPrimByte:
-        GetSetByteInstance(&obj, f, self, m, test);
+        GetSetByteInstance(&obj, &f, self, m, test);
         break;
       case Primitive::Type::kPrimChar:
-        GetSetCharInstance(&obj, f, self, m, test);
+        GetSetCharInstance(&obj, &f, self, m, test);
         break;
       case Primitive::Type::kPrimShort:
-        GetSetShortInstance(&obj, f, self, m, test);
+        GetSetShortInstance(&obj, &f, self, m, test);
         break;
       case Primitive::Type::kPrimInt:
-        GetSet32Instance(&obj, f, self, m, test);
+        GetSet32Instance(&obj, &f, self, m, test);
         break;
       case Primitive::Type::kPrimLong:
-        GetSet64Instance(&obj, f, self, m, test);
+        GetSet64Instance(&obj, &f, self, m, test);
         break;
       case Primitive::Type::kPrimNot:
         // Don't try array.
-        if (f->GetTypeDescriptor()[0] != '[') {
-          GetSetObjInstance(&obj, f, self, m, test);
+        if (f.GetTypeDescriptor()[0] != '[') {
+          GetSetObjInstance(&obj, &f, self, m, test);
         }
         break;
       default:
diff --git a/runtime/art_field.cc b/runtime/art_field.cc
index e4a5834..3737e0d 100644
--- a/runtime/art_field.cc
+++ b/runtime/art_field.cc
@@ -49,10 +49,9 @@
 
 ArtField* ArtField::FindInstanceFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
   DCHECK(klass != nullptr);
-  auto* instance_fields = klass->GetIFields();
-  for (size_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) {
-    if (instance_fields[i].GetOffset().Uint32Value() == field_offset) {
-      return &instance_fields[i];
+  for (ArtField& field : klass->GetIFields()) {
+    if (field.GetOffset().Uint32Value() == field_offset) {
+      return &field;
     }
   }
   // We did not find field in the class: look into superclass.
@@ -62,10 +61,9 @@
 
 ArtField* ArtField::FindStaticFieldWithOffset(mirror::Class* klass, uint32_t field_offset) {
   DCHECK(klass != nullptr);
-  auto* static_fields = klass->GetSFields();
-  for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
-    if (static_fields[i].GetOffset().Uint32Value() == field_offset) {
-      return &static_fields[i];
+  for (ArtField& field : klass->GetSFields()) {
+    if (field.GetOffset().Uint32Value() == field_offset) {
+      return &field;
     }
   }
   return nullptr;
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 350a0d4..35acd42 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -141,10 +141,10 @@
 #define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (36 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_ACCESS_FLAGS_OFFSET,
             art::mirror::Class::AccessFlagsOffset().Int32Value())
-#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (112 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (96 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_OBJECT_SIZE_OFFSET,
             art::mirror::Class::ObjectSizeOffset().Int32Value())
-#define MIRROR_CLASS_STATUS_OFFSET (124 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_STATUS_OFFSET (108 + MIRROR_OBJECT_HEADER_SIZE)
 ADD_TEST_EQ(MIRROR_CLASS_STATUS_OFFSET,
             art::mirror::Class::StatusOffset().Int32Value())
 
diff --git a/runtime/base/iteration_range.h b/runtime/base/iteration_range.h
index 6a0ef1f..cf02d32 100644
--- a/runtime/base/iteration_range.h
+++ b/runtime/base/iteration_range.h
@@ -49,6 +49,11 @@
   return IterationRange<Iter>(begin_it, end_it);
 }
 
+template <typename Iter>
+static inline IterationRange<Iter> MakeEmptyIterationRange(const Iter& it) {
+  return IterationRange<Iter>(it, it);
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_BASE_ITERATION_RANGE_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 56fae81..62ba907 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1058,12 +1058,11 @@
   CHECK(obj->GetClass()->GetClass() != nullptr) << "Null class class " << obj;
   if (obj->IsClass()) {
     auto klass = obj->AsClass();
-    ArtField* fields[2] = { klass->GetSFields(), klass->GetIFields() };
-    size_t num_fields[2] = { klass->NumStaticFields(), klass->NumInstanceFields() };
-    for (size_t i = 0; i < 2; ++i) {
-      for (size_t j = 0; j < num_fields[i]; ++j) {
-        CHECK_EQ(fields[i][j].GetDeclaringClass(), klass);
-      }
+    for (ArtField& field : klass->GetIFields()) {
+      CHECK_EQ(field.GetDeclaringClass(), klass);
+    }
+    for (ArtField& field : klass->GetSFields()) {
+      CHECK_EQ(field.GetDeclaringClass(), klass);
     }
     auto* runtime = Runtime::Current();
     auto* image_space = runtime->GetHeap()->GetImageSpace();
@@ -2282,23 +2281,31 @@
   }
 }
 
-ArtField* ClassLinker::AllocArtFieldArray(Thread* self, size_t length) {
-  auto* const la = Runtime::Current()->GetLinearAlloc();
-  auto* ptr = reinterpret_cast<ArtField*>(la->AllocArray<ArtField>(self, length));
-  CHECK(ptr!= nullptr);
-  std::uninitialized_fill_n(ptr, length, ArtField());
-  return ptr;
+LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self, size_t length) {
+  if (length == 0) {
+    return nullptr;
+  }
+  auto* ret = new(Runtime::Current()->GetLinearAlloc()->Alloc(
+      self, LengthPrefixedArray<ArtField>::ComputeSize(length))) LengthPrefixedArray<ArtField>(
+          length);
+  CHECK(ret != nullptr);
+  std::uninitialized_fill_n(&ret->At(0), length, ArtField());
+  return ret;
 }
 
-ArtMethod* ClassLinker::AllocArtMethodArray(Thread* self, size_t length) {
-  const size_t method_size = ArtMethod::ObjectSize(image_pointer_size_);
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(
-      Runtime::Current()->GetLinearAlloc()->Alloc(self, method_size * length));
-  CHECK_NE(ptr, 0u);
-  for (size_t i = 0; i < length; ++i) {
-    new(reinterpret_cast<void*>(ptr + i * method_size)) ArtMethod;
+LengthPrefixedArray<ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self, size_t length) {
+  if (length == 0) {
+    return nullptr;
   }
-  return reinterpret_cast<ArtMethod*>(ptr);
+  const size_t method_size = ArtMethod::ObjectSize(image_pointer_size_);
+  auto* ret = new (Runtime::Current()->GetLinearAlloc()->Alloc(
+      self, LengthPrefixedArray<ArtMethod>::ComputeSize(length, method_size)))
+          LengthPrefixedArray<ArtMethod>(length);
+  CHECK(ret != nullptr);
+  for (size_t i = 0; i < length; ++i) {
+    new(reinterpret_cast<void*>(&ret->At(i, method_size))) ArtMethod;
+  }
+  return ret;
 }
 
 void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file,
@@ -2313,8 +2320,7 @@
     // We allow duplicate definitions of the same field in a class_data_item
     // but ignore the repeated indexes here, b/21868015.
     ClassDataItemIterator it(dex_file, class_data);
-    ArtField* sfields =
-        it.NumStaticFields() != 0 ? AllocArtFieldArray(self, it.NumStaticFields()) : nullptr;
+    LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, it.NumStaticFields());
     size_t num_sfields = 0;
     uint32_t last_field_idx = 0u;
     for (; it.HasNextStaticField(); it.Next()) {
@@ -2322,17 +2328,15 @@
       DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.
       if (num_sfields == 0 || LIKELY(field_idx > last_field_idx)) {
         DCHECK_LT(num_sfields, it.NumStaticFields());
-        LoadField(it, klass, &sfields[num_sfields]);
+        LoadField(it, klass, &sfields->At(num_sfields));
         ++num_sfields;
         last_field_idx = field_idx;
       }
     }
-    klass->SetSFields(sfields);
-    klass->SetNumStaticFields(num_sfields);
+    klass->SetSFieldsPtr(sfields);
     DCHECK_EQ(klass->NumStaticFields(), num_sfields);
     // Load instance fields.
-    ArtField* ifields =
-        it.NumInstanceFields() != 0 ? AllocArtFieldArray(self, it.NumInstanceFields()) : nullptr;
+    LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self, it.NumInstanceFields());
     size_t num_ifields = 0u;
     last_field_idx = 0u;
     for (; it.HasNextInstanceField(); it.Next()) {
@@ -2340,7 +2344,7 @@
       DCHECK_GE(field_idx, last_field_idx);  // Ordering enforced by DexFileVerifier.
       if (num_ifields == 0 || LIKELY(field_idx > last_field_idx)) {
         DCHECK_LT(num_ifields, it.NumInstanceFields());
-        LoadField(it, klass, &ifields[num_ifields]);
+        LoadField(it, klass, &ifields->At(num_ifields));
         ++num_ifields;
         last_field_idx = field_idx;
       }
@@ -2352,18 +2356,11 @@
           << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
       // NOTE: Not shrinking the over-allocated sfields/ifields.
     }
-    klass->SetIFields(ifields);
-    klass->SetNumInstanceFields(num_ifields);
+    klass->SetIFieldsPtr(ifields);
     DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
     // Load methods.
-    if (it.NumDirectMethods() != 0) {
-      klass->SetDirectMethodsPtr(AllocArtMethodArray(self, it.NumDirectMethods()));
-    }
-    klass->SetNumDirectMethods(it.NumDirectMethods());
-    if (it.NumVirtualMethods() != 0) {
-      klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods()));
-    }
-    klass->SetNumVirtualMethods(it.NumVirtualMethods());
+    klass->SetDirectMethodsPtr(AllocArtMethodArray(self, it.NumDirectMethods()));
+    klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods()));
     size_t class_def_method_index = 0;
     uint32_t last_dex_method_index = DexFile::kDexNoIndex;
     size_t last_class_def_method_index = 0;
@@ -2807,12 +2804,10 @@
   return nullptr;
 }
 
-void ClassLinker::UpdateClassVirtualMethods(mirror::Class* klass, ArtMethod* new_methods,
-                                            size_t new_num_methods) {
-  // TODO: Fix the race condition here. b/22832610
-  klass->SetNumVirtualMethods(new_num_methods);
+void ClassLinker::UpdateClassVirtualMethods(mirror::Class* klass,
+                                            LengthPrefixedArray<ArtMethod>* new_methods) {
   klass->SetVirtualMethodsPtr(new_methods);
-  // Need to mark the card so that the remembered sets and mod union tables get update.
+  // Need to mark the card so that the remembered sets and mod union tables get updated.
   Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass);
 }
 
@@ -3257,25 +3252,24 @@
 
   // Instance fields are inherited, but we add a couple of static fields...
   const size_t num_fields = 2;
-  ArtField* sfields = AllocArtFieldArray(self, num_fields);
-  klass->SetSFields(sfields);
-  klass->SetNumStaticFields(num_fields);
+  LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, num_fields);
+  klass->SetSFieldsPtr(sfields);
 
   // 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
   // our proxy, so Class.getInterfaces doesn't return the flattened set.
-  ArtField* interfaces_sfield = &sfields[0];
-  interfaces_sfield->SetDexFieldIndex(0);
-  interfaces_sfield->SetDeclaringClass(klass.Get());
-  interfaces_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
+  ArtField& interfaces_sfield = sfields->At(0);
+  interfaces_sfield.SetDexFieldIndex(0);
+  interfaces_sfield.SetDeclaringClass(klass.Get());
+  interfaces_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
 
   // 2. Create a static field 'throws' that holds exceptions thrown by our methods.
-  ArtField* throws_sfield = &sfields[1];
-  throws_sfield->SetDexFieldIndex(1);
-  throws_sfield->SetDeclaringClass(klass.Get());
-  throws_sfield->SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
+  ArtField& throws_sfield = sfields->At(1);
+  throws_sfield.SetDexFieldIndex(1);
+  throws_sfield.SetDeclaringClass(klass.Get());
+  throws_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
 
   // Proxies have 1 direct method, the constructor
-  auto* directs = AllocArtMethodArray(self, 1);
+  LengthPrefixedArray<ArtMethod>* directs = AllocArtMethodArray(self, 1);
   // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
   // want to throw OOM in the future.
   if (UNLIKELY(directs == nullptr)) {
@@ -3283,13 +3277,12 @@
     return nullptr;
   }
   klass->SetDirectMethodsPtr(directs);
-  klass->SetNumDirectMethods(1u);
   CreateProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_));
 
   // Create virtual method using specified prototypes.
   auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
   DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
-    << PrettyClass(h_methods->GetClass());
+      << PrettyClass(h_methods->GetClass());
   const size_t num_virtual_methods = h_methods->GetLength();
   auto* virtuals = AllocArtMethodArray(self, num_virtual_methods);
   // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
@@ -3299,7 +3292,6 @@
     return nullptr;
   }
   klass->SetVirtualMethodsPtr(virtuals);
-  klass->SetNumVirtualMethods(num_virtual_methods);
   for (size_t i = 0; i < num_virtual_methods; ++i) {
     auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
     auto* prototype = h_methods->Get(i)->GetArtMethod();
@@ -3331,12 +3323,12 @@
   CHECK_NE(klass.Get(), new_class.Get());
   klass.Assign(new_class.Get());
 
-  CHECK_EQ(interfaces_sfield->GetDeclaringClass(), klass.Get());
-  interfaces_sfield->SetObject<false>(klass.Get(),
-                                      soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
-  CHECK_EQ(throws_sfield->GetDeclaringClass(), klass.Get());
-  throws_sfield->SetObject<false>(klass.Get(),
-      soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws));
+  CHECK_EQ(interfaces_sfield.GetDeclaringClass(), klass.Get());
+  interfaces_sfield.SetObject<false>(klass.Get(),
+                                     soa.Decode<mirror::ObjectArray<mirror::Class>*>(interfaces));
+  CHECK_EQ(throws_sfield.GetDeclaringClass(), klass.Get());
+  throws_sfield.SetObject<false>(
+      klass.Get(), soa.Decode<mirror::ObjectArray<mirror::ObjectArray<mirror::Class> >*>(throws));
 
   {
     // Lock on klass is released. Lock new class object.
@@ -3346,7 +3338,7 @@
 
   // sanity checks
   if (kIsDebugBuild) {
-    CHECK(klass->GetIFields() == nullptr);
+    CHECK(klass->GetIFieldsPtr() == nullptr);
     CheckProxyConstructor(klass->GetDirectMethod(0, image_pointer_size_));
 
     for (size_t i = 0; i < num_virtual_methods; ++i) {
@@ -3958,19 +3950,17 @@
 
 void ClassLinker::FixupTemporaryDeclaringClass(mirror::Class* temp_class,
                                                mirror::Class* new_class) {
-  ArtField* fields = new_class->GetIFields();
   DCHECK_EQ(temp_class->NumInstanceFields(), 0u);
-  for (size_t i = 0, count = new_class->NumInstanceFields(); i < count; i++) {
-    if (fields[i].GetDeclaringClass() == temp_class) {
-      fields[i].SetDeclaringClass(new_class);
+  for (ArtField& field : new_class->GetIFields()) {
+    if (field.GetDeclaringClass() == temp_class) {
+      field.SetDeclaringClass(new_class);
     }
   }
 
-  fields = new_class->GetSFields();
   DCHECK_EQ(temp_class->NumStaticFields(), 0u);
-  for (size_t i = 0, count = new_class->NumStaticFields(); i < count; i++) {
-    if (fields[i].GetDeclaringClass() == temp_class) {
-      fields[i].SetDeclaringClass(new_class);
+  for (ArtField& field : new_class->GetSFields()) {
+    if (field.GetDeclaringClass() == temp_class) {
+      field.SetDeclaringClass(new_class);
     }
   }
 
@@ -4057,10 +4047,10 @@
     // same ArtFields with the same If this occurs, it causes bugs in remembered sets since the GC
     // may not see any references to the from space and clean the card. Though there was references
     // to the from space that got marked by the first class.
-    klass->SetNumDirectMethods(0);
-    klass->SetNumVirtualMethods(0);
-    klass->SetNumStaticFields(0);
-    klass->SetNumInstanceFields(0);
+    klass->SetDirectMethodsPtrUnchecked(nullptr);
+    klass->SetVirtualMethodsPtr(nullptr);
+    klass->SetSFieldsPtrUnchecked(nullptr);
+    klass->SetIFieldsPtrUnchecked(nullptr);
     if (UNLIKELY(h_new_class.Get() == nullptr)) {
       self->AssertPendingOOMException();
       mirror::Class::SetStatus(klass, mirror::Class::kStatusError, self);
@@ -4863,7 +4853,7 @@
       const bool super_interface = is_super && extend_super_iftable;
       auto method_array(hs2.NewHandle(iftable->GetMethodArray(i)));
 
-      ArtMethod* input_virtual_methods = nullptr;
+      LengthPrefixedArray<ArtMethod>* input_virtual_methods = nullptr;
       Handle<mirror::PointerArray> input_vtable_array = NullHandle<mirror::PointerArray>();
       int32_t input_array_length = 0;
       if (super_interface) {
@@ -4898,8 +4888,7 @@
         // matter which direction we go.  We walk it backward anyway.)
         for (k = input_array_length - 1; k >= 0; --k) {
           ArtMethod* vtable_method = input_virtual_methods != nullptr ?
-              reinterpret_cast<ArtMethod*>(
-                  reinterpret_cast<uintptr_t>(input_virtual_methods) + method_size * k) :
+              &input_virtual_methods->At(k, method_size) :
               input_vtable_array->GetElementPtrSize<ArtMethod*>(k, image_pointer_size_);
           ArtMethod* vtable_method_for_name_comparison =
               vtable_method->GetInterfaceMethodIfProxy(image_pointer_size_);
@@ -4955,13 +4944,17 @@
     const size_t old_method_count = klass->NumVirtualMethods();
     const size_t new_method_count = old_method_count + miranda_methods.size();
     // Attempt to realloc to save RAM if possible.
-    ArtMethod* old_virtuals = klass->GetVirtualMethodsPtr();
+    LengthPrefixedArray<ArtMethod>* old_virtuals = klass->GetVirtualMethodsPtr();
     // The Realloced virtual methods aren't visiblef from the class roots, so there is no issue
     // where GCs could attempt to mark stale pointers due to memcpy. And since we overwrite the
     // realloced memory with out->CopyFrom, we are guaranteed to have objects in the to space since
     // CopyFrom has internal read barriers.
-    auto* virtuals = reinterpret_cast<ArtMethod*>(runtime->GetLinearAlloc()->Realloc(
-        self, old_virtuals, old_method_count * method_size, new_method_count * method_size));
+    const size_t old_size = old_virtuals != nullptr ?
+        LengthPrefixedArray<ArtMethod>::ComputeSize(old_method_count, method_size) : 0u;
+    const size_t new_size = LengthPrefixedArray<ArtMethod>::ComputeSize(new_method_count,
+                                                                        method_size);
+    auto* virtuals = new(runtime->GetLinearAlloc()->Realloc(
+        self, old_virtuals, old_size, new_size))LengthPrefixedArray<ArtMethod>(new_method_count);
     if (UNLIKELY(virtuals == nullptr)) {
       self->AssertPendingOOMException();
       self->EndAssertNoThreadSuspension(old_cause);
@@ -4970,7 +4963,7 @@
     ScopedArenaUnorderedMap<ArtMethod*, ArtMethod*> move_table(allocator.Adapter());
     if (virtuals != old_virtuals) {
       // Maps from heap allocated miranda method to linear alloc miranda method.
-      StrideIterator<ArtMethod> out(reinterpret_cast<uintptr_t>(virtuals), method_size);
+      StrideIterator<ArtMethod> out = virtuals->Begin(method_size);
       // Copy over the old methods + miranda methods.
       for (auto& m : klass->GetVirtualMethods(image_pointer_size_)) {
         move_table.emplace(&m, &*out);
@@ -4980,8 +4973,7 @@
         ++out;
       }
     }
-    StrideIterator<ArtMethod> out(
-        reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
+    StrideIterator<ArtMethod> out(virtuals->Begin(method_size) + old_method_count);
     // Copy over miranda methods before copying vtable since CopyOf may cause thread suspension and
     // we want the roots of the miranda methods to get visited.
     for (ArtMethod* mir_method : miranda_methods) {
@@ -4990,7 +4982,7 @@
       move_table.emplace(mir_method, &*out);
       ++out;
     }
-    UpdateClassVirtualMethods(klass.Get(), virtuals, new_method_count);
+    UpdateClassVirtualMethods(klass.Get(), virtuals);
     // Done copying methods, they are all roots in the class now, so we can end the no thread
     // suspension assert.
     self->EndAssertNoThreadSuspension(old_cause);
@@ -5003,8 +4995,7 @@
       self->AssertPendingOOMException();
       return false;
     }
-    out = StrideIterator<ArtMethod>(
-        reinterpret_cast<uintptr_t>(virtuals) + old_method_count * method_size, method_size);
+    out = StrideIterator<ArtMethod>(virtuals->Begin(method_size) + old_method_count);
     size_t vtable_pos = old_vtable_count;
     for (size_t i = old_method_count; i < new_method_count; ++i) {
       // Leave the declaring class alone as type indices are relative to it
@@ -5058,7 +5049,7 @@
     }
     // Put some random garbage in old virtuals to help find stale pointers.
     if (virtuals != old_virtuals) {
-      memset(old_virtuals, 0xFEu, ArtMethod::ObjectSize(image_pointer_size_) * old_method_count);
+      memset(old_virtuals, 0xFEu, old_size);
     }
   } else {
     self->EndAssertNoThreadSuspension(old_cause);
@@ -5120,7 +5111,8 @@
                              size_t* class_size) {
   self->AllowThreadSuspension();
   const size_t num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
-  ArtField* const fields = is_static ? klass->GetSFields() : klass->GetIFields();
+  LengthPrefixedArray<ArtField>* const fields = is_static ? klass->GetSFieldsPtr() :
+      klass->GetIFieldsPtr();
 
   // Initialize field_offset
   MemberOffset field_offset(0);
@@ -5143,7 +5135,7 @@
   const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension(
       "Naked ArtField references in deque");
   for (size_t i = 0; i < num_fields; i++) {
-    grouped_and_sorted_fields.push_back(&fields[i]);
+    grouped_and_sorted_fields.push_back(&fields->At(i));
   }
   std::sort(grouped_and_sorted_fields.begin(), grouped_and_sorted_fields.end(),
             LinkFieldsComparator());
@@ -5188,7 +5180,8 @@
     // We know there are no non-reference fields in the Reference classes, and we know
     // that 'referent' is alphabetically last, so this is easy...
     CHECK_EQ(num_reference_fields, num_fields) << PrettyClass(klass.Get());
-    CHECK_STREQ(fields[num_fields - 1].GetName(), "referent") << PrettyClass(klass.Get());
+    CHECK_STREQ(fields->At(num_fields - 1).GetName(), "referent")
+        << PrettyClass(klass.Get());
     --num_reference_fields;
   }
 
@@ -5222,15 +5215,15 @@
                                     sizeof(mirror::HeapReference<mirror::Object>));
     MemberOffset current_ref_offset = start_ref_offset;
     for (size_t i = 0; i < num_fields; i++) {
-      ArtField* field = &fields[i];
+      ArtField* field = &fields->At(i);
       VLOG(class_linker) << "LinkFields: " << (is_static ? "static" : "instance")
           << " class=" << PrettyClass(klass.Get()) << " field=" << PrettyField(field) << " offset="
           << field->GetOffsetDuringLinking();
       if (i != 0) {
-        ArtField* const prev_field = &fields[i - 1];
+        ArtField* const prev_field = &fields->At(i - 1);
         // NOTE: The field names can be the same. This is not possible in the Java language
         // but it's valid Java/dex bytecode and for example proguard can generate such bytecode.
-        CHECK_LE(strcmp(prev_field->GetName(), field->GetName()), 0);
+        DCHECK_LE(strcmp(prev_field->GetName(), field->GetName()), 0);
       }
       Primitive::Type type = field->GetTypeAsPrimitiveType();
       bool is_primitive = type != Primitive::kPrimNot;
@@ -5868,7 +5861,8 @@
 }
 
 ArtMethod* ClassLinker::CreateRuntimeMethod() {
-  ArtMethod* method = AllocArtMethodArray(Thread::Current(), 1);
+  const size_t method_size = ArtMethod::ObjectSize(image_pointer_size_);
+  ArtMethod* method = &AllocArtMethodArray(Thread::Current(), 1)->At(0, method_size);
   CHECK(method != nullptr);
   method->SetDexMethodIndex(DexFile::kDexNoIndex);
   CHECK(method->IsRuntimeMethod());
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index c53ff61..17d6be6 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -344,9 +344,9 @@
   mirror::ObjectArray<mirror::String>* AllocStringArray(Thread* self, size_t length)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  ArtField* AllocArtFieldArray(Thread* self, size_t length);
+  LengthPrefixedArray<ArtField>* AllocArtFieldArray(Thread* self, size_t length);
 
-  ArtMethod* AllocArtMethodArray(Thread* self, size_t length);
+  LengthPrefixedArray<ArtMethod>* AllocArtMethodArray(Thread* self, size_t length);
 
   mirror::PointerArray* AllocPointerArray(Thread* self, size_t length)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
@@ -694,9 +694,10 @@
   bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics, bool can_init_parents)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  void UpdateClassVirtualMethods(mirror::Class* klass, ArtMethod* new_methods,
-                                 size_t new_num_methods)
-      SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Locks::classlinker_classes_lock_);
+  void UpdateClassVirtualMethods(mirror::Class* klass,
+                                 LengthPrefixedArray<ArtMethod>* new_methods)
+      SHARED_REQUIRES(Locks::mutator_lock_)
+      REQUIRES(!Locks::classlinker_classes_lock_);
 
   std::vector<const DexFile*> boot_class_path_;
   std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 3f8259a..4212dda 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -500,14 +500,10 @@
     addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
     addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
-    addOffset(OFFSETOF_MEMBER(mirror::Class, num_direct_methods_), "numDirectMethods");
-    addOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_),
               "numReferenceInstanceFields");
     addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),
               "numReferenceStaticFields");
-    addOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields");
-    addOffset(OFFSETOF_MEMBER(mirror::Class, num_virtual_methods_), "numVirtualMethods");
     addOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize");
     addOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType");
     addOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),
@@ -841,21 +837,21 @@
   NullHandle<mirror::ClassLoader> class_loader;
   mirror::Class* c;
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Boolean;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Byte;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Character;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Double;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Float;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Integer;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Long;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
   c = class_linker_->FindClass(soa.Self(), "Ljava/lang/Short;", class_loader);
-  EXPECT_STREQ("value", c->GetIFields()[0].GetName());
+  EXPECT_STREQ("value", c->GetIFieldsPtr()->At(0).GetName());
 }
 
 TEST_F(ClassLinkerTest, TwoClassLoadersOneClass) {
diff --git a/runtime/gc/accounting/space_bitmap.cc b/runtime/gc/accounting/space_bitmap.cc
index 7914b66..b43f77f 100644
--- a/runtime/gc/accounting/space_bitmap.cc
+++ b/runtime/gc/accounting/space_bitmap.cc
@@ -195,11 +195,9 @@
     WalkInstanceFields(visited, callback, obj, super, arg);
   }
   // Walk instance fields
-  auto* fields = klass->GetIFields();
-  for (size_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) {
-    ArtField* field = &fields[i];
-    if (!field->IsPrimitiveType()) {
-      mirror::Object* value = field->GetObj(obj);
+  for (ArtField& field : klass->GetIFields()) {
+    if (!field.IsPrimitiveType()) {
+      mirror::Object* value = field.GetObj(obj);
       if (value != nullptr) {
         WalkFieldsInOrder(visited, callback, value, arg);
       }
@@ -222,11 +220,9 @@
   WalkInstanceFields(visited, callback, obj, klass, arg);
   // Walk static fields of a Class
   if (obj->IsClass()) {
-    auto* sfields = klass->GetSFields();
-    for (size_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
-      ArtField* field = &sfields[i];
-      if (!field->IsPrimitiveType()) {
-        mirror::Object* value = field->GetObj(nullptr);
+    for (ArtField& field : klass->GetSFields()) {
+      if (!field.IsPrimitiveType()) {
+        mirror::Object* value = field.GetObj(nullptr);
         if (value != nullptr) {
           WalkFieldsInOrder(visited, callback, value, arg);
         }
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 5f617bd..59e39df 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2912,14 +2912,10 @@
           if (!obj->IsObjectArray()) {
             mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
             CHECK(klass != nullptr);
-            auto* fields = is_static ? klass->GetSFields() : klass->GetIFields();
-            auto num_fields = is_static ? klass->NumStaticFields() : klass->NumInstanceFields();
-            CHECK_EQ(fields == nullptr, num_fields == 0u);
-            for (size_t i = 0; i < num_fields; ++i) {
-              ArtField* cur = &fields[i];
-              if (cur->GetOffset().Int32Value() == offset.Int32Value()) {
+            for (ArtField& field : is_static ? klass->GetSFields() : klass->GetIFields()) {
+              if (field.GetOffset().Int32Value() == offset.Int32Value()) {
                 LOG(ERROR) << (is_static ? "Static " : "") << "field in the live stack is "
-                          << PrettyField(cur);
+                           << PrettyField(&field);
                 break;
               }
             }
diff --git a/runtime/image.cc b/runtime/image.cc
index 44193da..ba1e58b 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -24,7 +24,7 @@
 namespace art {
 
 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '7', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '1', '8', '\0' };
 
 ImageHeader::ImageHeader(uint32_t image_begin,
                          uint32_t image_size,
@@ -147,4 +147,26 @@
   return os << "size=" << section.Size() << " range=" << section.Offset() << "-" << section.End();
 }
 
+void ImageSection::VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const {
+  for (size_t pos = 0; pos < Size(); ) {
+    auto* array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(base + Offset() + pos);
+    for (size_t i = 0; i < array->Length(); ++i) {
+      visitor->Visit(&array->At(i, sizeof(ArtField)));
+    }
+    pos += array->ComputeSize(array->Length(), sizeof(ArtField));
+  }
+}
+
+void ImageSection::VisitPackedArtMethods(ArtMethodVisitor* visitor,
+                                         uint8_t* base,
+                                         size_t method_size) const {
+  for (size_t pos = 0; pos < Size(); ) {
+    auto* array = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(base + Offset() + pos);
+    for (size_t i = 0; i < array->Length(); ++i) {
+      visitor->Visit(&array->At(i, method_size));
+    }
+    pos += array->ComputeSize(array->Length(), method_size);
+  }
+}
+
 }  // namespace art
diff --git a/runtime/image.h b/runtime/image.h
index cc98ba6..eb26f7f 100644
--- a/runtime/image.h
+++ b/runtime/image.h
@@ -24,6 +24,23 @@
 
 namespace art {
 
+class ArtField;
+class ArtMethod;
+
+class ArtMethodVisitor {
+ public:
+  virtual ~ArtMethodVisitor() {}
+
+  virtual void Visit(ArtMethod* method) = 0;
+};
+
+class ArtFieldVisitor {
+ public:
+  virtual ~ArtFieldVisitor() {}
+
+  virtual void Visit(ArtField* method) = 0;
+};
+
 class PACKED(4) ImageSection {
  public:
   ImageSection() : offset_(0), size_(0) { }
@@ -47,6 +64,12 @@
     return offset - offset_ < size_;
   }
 
+  // Visit ArtMethods in the section starting at base.
+  void VisitPackedArtMethods(ArtMethodVisitor* visitor, uint8_t* base, size_t method_size) const;
+
+  // Visit ArtMethods in the section starting at base.
+  void VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const;
+
  private:
   uint32_t offset_;
   uint32_t size_;
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 22701ac..c559389 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -229,20 +229,16 @@
   mirror::Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
   mirror::String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
   ArtField* found = nullptr;
-  ArtField* fields = klass->GetIFields();
-  for (int32_t i = 0, count = klass->NumInstanceFields(); i < count; ++i) {
-    ArtField* f = &fields[i];
-    if (name2->Equals(f->GetName())) {
-      found = f;
+  for (ArtField& field : klass->GetIFields()) {
+    if (name2->Equals(field.GetName())) {
+      found = &field;
       break;
     }
   }
   if (found == nullptr) {
-    fields = klass->GetSFields();
-    for (int32_t i = 0, count = klass->NumStaticFields(); i < count; ++i) {
-      ArtField* f = &fields[i];
-      if (name2->Equals(f->GetName())) {
-        found = f;
+    for (ArtField& field : klass->GetSFields()) {
+      if (name2->Equals(field.GetName())) {
+        found = &field;
         break;
       }
     }
diff --git a/runtime/jit/jit_code_cache_test.cc b/runtime/jit/jit_code_cache_test.cc
index cd123b9..555ad7c 100644
--- a/runtime/jit/jit_code_cache_test.cc
+++ b/runtime/jit/jit_code_cache_test.cc
@@ -50,7 +50,7 @@
   ASSERT_TRUE(code_cache->ContainsCodePtr(reserved_code));
   ASSERT_EQ(code_cache->NumMethods(), 1u);
   ClassLinker* const cl = Runtime::Current()->GetClassLinker();
-  auto* method = cl->AllocArtMethodArray(soa.Self(), 1);
+  ArtMethod* method = &cl->AllocArtMethodArray(soa.Self(), 1)->At(0, 0);
   ASSERT_FALSE(code_cache->ContainsMethod(method));
   method->SetEntryPointFromQuickCompiledCode(reserved_code);
   ASSERT_TRUE(code_cache->ContainsMethod(method));
diff --git a/runtime/length_prefixed_array.h b/runtime/length_prefixed_array.h
new file mode 100644
index 0000000..82176e3
--- /dev/null
+++ b/runtime/length_prefixed_array.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 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_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
+#define ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
+
+#include <stddef.h>  // for offsetof()
+
+#include "linear_alloc.h"
+#include "stride_iterator.h"
+#include "base/iteration_range.h"
+
+namespace art {
+
+template<typename T>
+class LengthPrefixedArray {
+ public:
+  explicit LengthPrefixedArray(uint64_t length) : length_(length) {}
+
+  T& At(size_t index, size_t element_size = sizeof(T)) {
+    DCHECK_LT(index, length_);
+    return *reinterpret_cast<T*>(&data_[0] + index * element_size);
+  }
+
+  StrideIterator<T> Begin(size_t element_size = sizeof(T)) {
+    return StrideIterator<T>(reinterpret_cast<T*>(&data_[0]), element_size);
+  }
+
+  StrideIterator<T> End(size_t element_size = sizeof(T)) {
+    return StrideIterator<T>(reinterpret_cast<T*>(&data_[0] + element_size * length_),
+                             element_size);
+  }
+
+  static size_t OffsetOfElement(size_t index, size_t element_size = sizeof(T)) {
+    return offsetof(LengthPrefixedArray<T>, data_) + index * element_size;
+  }
+
+  static size_t ComputeSize(size_t num_elements, size_t element_size = sizeof(T)) {
+    return sizeof(LengthPrefixedArray<T>) + num_elements * element_size;
+  }
+
+  uint64_t Length() const {
+    return length_;
+  }
+
+ private:
+  uint64_t length_;  // 64 bits for padding reasons.
+  uint8_t data_[0];
+};
+
+// Returns empty iteration range if the array is null.
+template<typename T>
+IterationRange<StrideIterator<T>> MakeIterationRangeFromLengthPrefixedArray(
+    LengthPrefixedArray<T>* arr, size_t element_size) {
+  return arr != nullptr ?
+      MakeIterationRange(arr->Begin(element_size), arr->End(element_size)) :
+      MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
diff --git a/runtime/linear_alloc.h b/runtime/linear_alloc.h
index 743ee77..1b21527 100644
--- a/runtime/linear_alloc.h
+++ b/runtime/linear_alloc.h
@@ -33,7 +33,7 @@
   // Realloc never frees the input pointer, it is the caller's job to do this if necessary.
   void* Realloc(Thread* self, void* ptr, size_t old_size, size_t new_size) REQUIRES(!lock_);
 
-  // Allocate and construct an array of structs of type T.
+  // Allocate an array of structs of type T.
   template<class T>
   T* AllocArray(Thread* self, size_t elements) REQUIRES(!lock_) {
     return reinterpret_cast<T*>(Alloc(self, elements * sizeof(T)));
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 6568487..887e204 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -28,6 +28,7 @@
 #include "dex_file.h"
 #include "gc/heap-inl.h"
 #include "iftable.h"
+#include "length_prefixed_array.h"
 #include "object_array-inl.h"
 #include "read_barrier-inl.h"
 #include "reference-inl.h"
@@ -61,25 +62,28 @@
   return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_));
 }
 
-inline ArtMethod* Class::GetDirectMethodsPtr() {
+inline LengthPrefixedArray<ArtMethod>* Class::GetDirectMethodsPtr() {
   DCHECK(IsLoaded() || IsErroneous());
   return GetDirectMethodsPtrUnchecked();
 }
 
-inline ArtMethod* Class::GetDirectMethodsPtrUnchecked() {
-  return reinterpret_cast<ArtMethod*>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_)));
+inline LengthPrefixedArray<ArtMethod>* Class::GetDirectMethodsPtrUnchecked() {
+  return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
+      GetField64(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_)));
 }
 
-inline ArtMethod* Class::GetVirtualMethodsPtrUnchecked() {
-  return reinterpret_cast<ArtMethod*>(GetField64(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_)));
+inline LengthPrefixedArray<ArtMethod>* Class::GetVirtualMethodsPtrUnchecked() {
+  return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
+      GetField64(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_)));
 }
 
-inline void Class::SetDirectMethodsPtr(ArtMethod* new_direct_methods) {
+inline void Class::SetDirectMethodsPtr(LengthPrefixedArray<ArtMethod>* new_direct_methods) {
   DCHECK(GetDirectMethodsPtrUnchecked() == nullptr);
   SetDirectMethodsPtrUnchecked(new_direct_methods);
 }
 
-inline void Class::SetDirectMethodsPtrUnchecked(ArtMethod* new_direct_methods) {
+inline void Class::SetDirectMethodsPtrUnchecked(
+    LengthPrefixedArray<ArtMethod>* new_direct_methods) {
   SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
                     reinterpret_cast<uint64_t>(new_direct_methods));
 }
@@ -88,25 +92,23 @@
   CheckPointerSize(pointer_size);
   auto* methods = GetDirectMethodsPtrUnchecked();
   DCHECK(methods != nullptr);
-  return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) +
-      ArtMethod::ObjectSize(pointer_size) * i);
+  return &methods->At(i, ArtMethod::ObjectSize(pointer_size));
 }
 
 inline ArtMethod* Class::GetDirectMethod(size_t i, size_t pointer_size) {
   CheckPointerSize(pointer_size);
   auto* methods = GetDirectMethodsPtr();
   DCHECK(methods != nullptr);
-  return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) +
-      ArtMethod::ObjectSize(pointer_size) * i);
+  return &methods->At(i, ArtMethod::ObjectSize(pointer_size));
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline ArtMethod* Class::GetVirtualMethodsPtr() {
+inline LengthPrefixedArray<ArtMethod>* Class::GetVirtualMethodsPtr() {
   DCHECK(IsLoaded<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
   return GetVirtualMethodsPtrUnchecked();
 }
 
-inline void Class::SetVirtualMethodsPtr(ArtMethod* new_virtual_methods) {
+inline void Class::SetVirtualMethodsPtr(LengthPrefixedArray<ArtMethod>* new_virtual_methods) {
   // TODO: we reassign virtual methods to grow the table for miranda
   // methods.. they should really just be assigned once.
   SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_),
@@ -129,10 +131,9 @@
 
 inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, size_t pointer_size) {
   CheckPointerSize(pointer_size);
-  auto* methods = GetVirtualMethodsPtrUnchecked();
+  LengthPrefixedArray<ArtMethod>* methods = GetVirtualMethodsPtrUnchecked();
   DCHECK(methods != nullptr);
-  return reinterpret_cast<ArtMethod*>(reinterpret_cast<uintptr_t>(methods) +
-      ArtMethod::ObjectSize(pointer_size) * i);
+  return &methods->At(i, ArtMethod::ObjectSize(pointer_size));
 }
 
 inline PointerArray* Class::GetVTable() {
@@ -423,9 +424,9 @@
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable);
 }
 
-inline ArtField* Class::GetIFields() {
+inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtr() {
   DCHECK(IsLoaded() || IsErroneous());
-  return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+  return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
 }
 
 inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() {
@@ -458,46 +459,44 @@
   return MemberOffset(base);
 }
 
-inline void Class::SetIFields(ArtField* new_ifields) {
-  DCHECK(GetIFieldsUnchecked() == nullptr);
+inline void Class::SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields) {
+  DCHECK(GetIFieldsPtrUnchecked() == nullptr);
   return SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
 }
 
-inline void Class::SetIFieldsUnchecked(ArtField* new_ifields) {
+inline void Class::SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_ifields) {
   SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields);
 }
 
-inline ArtField* Class::GetSFieldsUnchecked() {
-  return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
+inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtrUnchecked() {
+  return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_));
 }
 
-inline ArtField* Class::GetIFieldsUnchecked() {
-  return GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
+inline LengthPrefixedArray<ArtField>* Class::GetIFieldsPtrUnchecked() {
+  return GetFieldPtr<LengthPrefixedArray<ArtField>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_));
 }
 
-inline ArtField* Class::GetSFields() {
+inline LengthPrefixedArray<ArtField>* Class::GetSFieldsPtr() {
   DCHECK(IsLoaded() || IsErroneous()) << GetStatus();
-  return GetSFieldsUnchecked();
+  return GetSFieldsPtrUnchecked();
 }
 
-inline void Class::SetSFields(ArtField* new_sfields) {
+inline void Class::SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields) {
   DCHECK((IsRetired() && new_sfields == nullptr) ||
          GetFieldPtr<ArtField*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_)) == nullptr);
   SetFieldPtr<false>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
 }
 
-inline void Class::SetSFieldsUnchecked(ArtField* new_sfields) {
+inline void Class::SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields) {
   SetFieldPtr<false, true, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields);
 }
 
 inline ArtField* Class::GetStaticField(uint32_t i) {
-  DCHECK_LT(i, NumStaticFields());
-  return &GetSFields()[i];
+  return &GetSFieldsPtr()->At(i);
 }
 
 inline ArtField* Class::GetInstanceField(uint32_t i) {
-  DCHECK_LT(i, NumInstanceFields());
-  return &GetIFields()[i];
+  return &GetIFieldsPtr()->At(i);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -813,85 +812,54 @@
 
 template<class Visitor>
 void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) {
-  ArtField* const sfields = GetSFieldsUnchecked();
-  // Since we visit class roots while we may be writing these fields, check against null.
-  if (sfields != nullptr) {
-    for (size_t i = 0, count = NumStaticFields(); i < count; ++i) {
-      auto* f = &sfields[i];
-      // Visit roots first in case the declaring class gets moved.
-      f->VisitRoots(visitor);
-      if (kIsDebugBuild && IsResolved()) {
-        CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus();
-      }
+  for (ArtField& field : GetSFieldsUnchecked()) {
+    // Visit roots first in case the declaring class gets moved.
+    field.VisitRoots(visitor);
+    if (kIsDebugBuild && IsResolved()) {
+      CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
     }
   }
-  ArtField* const ifields = GetIFieldsUnchecked();
-  if (ifields != nullptr) {
-    for (size_t i = 0, count = NumInstanceFields(); i < count; ++i) {
-      auto* f = &ifields[i];
-      // Visit roots first in case the declaring class gets moved.
-      f->VisitRoots(visitor);
-      if (kIsDebugBuild && IsResolved()) {
-        CHECK_EQ(f->GetDeclaringClass(), this) << GetStatus();
-      }
+  for (ArtField& field : GetIFieldsUnchecked()) {
+    // Visit roots first in case the declaring class gets moved.
+    field.VisitRoots(visitor);
+    if (kIsDebugBuild && IsResolved()) {
+      CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
     }
   }
-  // We may see GetDirectMethodsPtr() == null with NumDirectMethods() != 0 if the root marking
-  // thread reads a null DirectMethodsBegin() but a non null DirectMethodsBegin() due to a race
-  // SetDirectMethodsPtr from class linking. Same for virtual methods.
-  // In this case, it is safe to avoid marking the roots since we must be either the CC or CMS. If
-  // we are CMS then the roots are already marked through other sources, otherwise the roots are
-  // already marked due to the to-space invariant.
-  // Unchecked versions since we may visit roots of classes that aren't yet loaded.
-  if (GetDirectMethodsPtrUnchecked() != nullptr) {
-    for (auto& m : GetDirectMethods(pointer_size)) {
-      m.VisitRoots(visitor);
-    }
+  for (ArtMethod& method : GetDirectMethods(pointer_size)) {
+    method.VisitRoots(visitor);
   }
-  if (GetVirtualMethodsPtrUnchecked() != nullptr) {
-    for (auto& m : GetVirtualMethods(pointer_size)) {
-      m.VisitRoots(visitor);
-    }
+  for (ArtMethod& method : GetVirtualMethods(pointer_size)) {
+    method.VisitRoots(visitor);
   }
 }
 
-inline StrideIterator<ArtMethod> Class::DirectMethodsBegin(size_t pointer_size)  {
-  CheckPointerSize(pointer_size);
-  auto* methods = GetDirectMethodsPtrUnchecked();
-  auto stride = ArtMethod::ObjectSize(pointer_size);
-  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods), stride);
-}
-
-inline StrideIterator<ArtMethod> Class::DirectMethodsEnd(size_t pointer_size) {
-  CheckPointerSize(pointer_size);
-  auto* methods = GetDirectMethodsPtrUnchecked();
-  auto stride = ArtMethod::ObjectSize(pointer_size);
-  auto count = NumDirectMethods();
-  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods) + stride * count, stride);
-}
-
 inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) {
   CheckPointerSize(pointer_size);
-  return MakeIterationRange(DirectMethodsBegin(pointer_size), DirectMethodsEnd(pointer_size));
-}
-
-inline StrideIterator<ArtMethod> Class::VirtualMethodsBegin(size_t pointer_size)  {
-  CheckPointerSize(pointer_size);
-  auto* methods = GetVirtualMethodsPtrUnchecked();
-  auto stride = ArtMethod::ObjectSize(pointer_size);
-  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods), stride);
-}
-
-inline StrideIterator<ArtMethod> Class::VirtualMethodsEnd(size_t pointer_size) {
-  CheckPointerSize(pointer_size);
-  auto* methods = GetVirtualMethodsPtrUnchecked();
-  auto stride = ArtMethod::ObjectSize(pointer_size);
-  auto count = NumVirtualMethods();
-  return StrideIterator<ArtMethod>(reinterpret_cast<uintptr_t>(methods) + stride * count, stride);
+  return MakeIterationRangeFromLengthPrefixedArray(GetDirectMethodsPtrUnchecked(),
+                                                   ArtMethod::ObjectSize(pointer_size));
 }
 
 inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(size_t pointer_size) {
-  return MakeIterationRange(VirtualMethodsBegin(pointer_size), VirtualMethodsEnd(pointer_size));
+  CheckPointerSize(pointer_size);
+  return MakeIterationRangeFromLengthPrefixedArray(GetVirtualMethodsPtrUnchecked(),
+                                                   ArtMethod::ObjectSize(pointer_size));
+}
+
+inline IterationRange<StrideIterator<ArtField>> Class::GetIFields() {
+  return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtr(), sizeof(ArtField));
+}
+
+inline IterationRange<StrideIterator<ArtField>> Class::GetSFields() {
+  return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtr(), sizeof(ArtField));
+}
+
+inline IterationRange<StrideIterator<ArtField>> Class::GetIFieldsUnchecked() {
+  return MakeIterationRangeFromLengthPrefixedArray(GetIFieldsPtrUnchecked(), sizeof(ArtField));
+}
+
+inline IterationRange<StrideIterator<ArtField>> Class::GetSFieldsUnchecked() {
+  return MakeIterationRangeFromLengthPrefixedArray(GetSFieldsPtrUnchecked(), sizeof(ArtField));
 }
 
 inline MemberOffset Class::EmbeddedImTableOffset(size_t pointer_size) {
@@ -940,6 +908,26 @@
   }
 }
 
+inline uint32_t Class::NumDirectMethods() {
+  LengthPrefixedArray<ArtMethod>* arr = GetDirectMethodsPtrUnchecked();
+  return arr != nullptr ? arr->Length() : 0u;
+}
+
+inline uint32_t Class::NumVirtualMethods() {
+  LengthPrefixedArray<ArtMethod>* arr = GetVirtualMethodsPtrUnchecked();
+  return arr != nullptr ? arr->Length() : 0u;
+}
+
+inline uint32_t Class::NumInstanceFields() {
+  LengthPrefixedArray<ArtField>* arr = GetIFieldsPtrUnchecked();
+  return arr != nullptr ? arr->Length() : 0u;
+}
+
+inline uint32_t Class::NumStaticFields() {
+  LengthPrefixedArray<ArtField>* arr = GetSFieldsPtrUnchecked();
+  return arr != nullptr ? arr->Length() : 0u;
+}
+
 }  // namespace mirror
 }  // namespace art
 
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index d95bcd8..f138936 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -41,7 +41,7 @@
 class ArtMethod;
 struct ClassOffsets;
 template<class T> class Handle;
-template<class T> class Handle;
+template<typename T> class LengthPrefixedArray;
 class Signature;
 class StringPiece;
 template<size_t kNumReferences> class PACKED(4) StackHandleScope;
@@ -656,21 +656,15 @@
   // Also updates the dex_cache_strings_ variable from new_dex_cache.
   void SetDexCache(DexCache* new_dex_cache) SHARED_REQUIRES(Locks::mutator_lock_);
 
-  ALWAYS_INLINE StrideIterator<ArtMethod> DirectMethodsBegin(size_t pointer_size)
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
-  ALWAYS_INLINE StrideIterator<ArtMethod> DirectMethodsEnd(size_t pointer_size)
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
   ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDirectMethods(size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  ArtMethod* GetDirectMethodsPtr() SHARED_REQUIRES(Locks::mutator_lock_);
+  LengthPrefixedArray<ArtMethod>* GetDirectMethodsPtr() SHARED_REQUIRES(Locks::mutator_lock_);
 
-  void SetDirectMethodsPtr(ArtMethod* new_direct_methods)
+  void SetDirectMethodsPtr(LengthPrefixedArray<ArtMethod>* new_direct_methods)
       SHARED_REQUIRES(Locks::mutator_lock_);
   // Used by image writer.
-  void SetDirectMethodsPtrUnchecked(ArtMethod* new_direct_methods)
+  void SetDirectMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod>* new_direct_methods)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
   ALWAYS_INLINE ArtMethod* GetDirectMethod(size_t i, size_t pointer_size)
@@ -683,35 +677,20 @@
         SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Returns the number of static, private, and constructor methods.
-  ALWAYS_INLINE uint32_t NumDirectMethods() SHARED_REQUIRES(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_direct_methods_));
-  }
-  void SetNumDirectMethods(uint32_t num) SHARED_REQUIRES(Locks::mutator_lock_) {
-    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_direct_methods_), num);
-  }
+  ALWAYS_INLINE uint32_t NumDirectMethods() SHARED_REQUIRES(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ALWAYS_INLINE ArtMethod* GetVirtualMethodsPtr() SHARED_REQUIRES(Locks::mutator_lock_);
-
-  ALWAYS_INLINE StrideIterator<ArtMethod> VirtualMethodsBegin(size_t pointer_size)
-      SHARED_REQUIRES(Locks::mutator_lock_);
-
-  ALWAYS_INLINE StrideIterator<ArtMethod> VirtualMethodsEnd(size_t pointer_size)
+  ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetVirtualMethodsPtr()
       SHARED_REQUIRES(Locks::mutator_lock_);
 
   ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetVirtualMethods(size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  void SetVirtualMethodsPtr(ArtMethod* new_virtual_methods)
+  void SetVirtualMethodsPtr(LengthPrefixedArray<ArtMethod>* new_virtual_methods)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Returns the number of non-inherited virtual methods.
-  ALWAYS_INLINE uint32_t NumVirtualMethods() SHARED_REQUIRES(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_virtual_methods_));
-  }
-  void SetNumVirtualMethods(uint32_t num) SHARED_REQUIRES(Locks::mutator_lock_) {
-    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_virtual_methods_), num);
-  }
+  ALWAYS_INLINE uint32_t NumVirtualMethods() SHARED_REQUIRES(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ArtMethod* GetVirtualMethod(size_t i, size_t pointer_size)
@@ -859,21 +838,19 @@
   ALWAYS_INLINE void SetIfTable(IfTable* new_iftable) SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Get instance fields of the class (See also GetSFields).
-  ArtField* GetIFields() SHARED_REQUIRES(Locks::mutator_lock_);
+  LengthPrefixedArray<ArtField>* GetIFieldsPtr() SHARED_REQUIRES(Locks::mutator_lock_);
 
-  void SetIFields(ArtField* new_ifields) SHARED_REQUIRES(Locks::mutator_lock_);
+  ALWAYS_INLINE IterationRange<StrideIterator<ArtField>> GetIFields()
+      SHARED_REQUIRES(Locks::mutator_lock_);
+
+  void SetIFieldsPtr(LengthPrefixedArray<ArtField>* new_ifields)
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Unchecked edition has no verification flags.
-  void SetIFieldsUnchecked(ArtField* new_sfields) SHARED_REQUIRES(Locks::mutator_lock_);
+  void SetIFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields)
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
-  uint32_t NumInstanceFields() SHARED_REQUIRES(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_instance_fields_));
-  }
-
-  void SetNumInstanceFields(uint32_t num) SHARED_REQUIRES(Locks::mutator_lock_) {
-    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_instance_fields_), num);
-  }
-
+  uint32_t NumInstanceFields() SHARED_REQUIRES(Locks::mutator_lock_);
   ArtField* GetInstanceField(uint32_t i) SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Returns the number of instance fields containing reference types.
@@ -927,20 +904,18 @@
       SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Gets the static fields of the class.
-  ArtField* GetSFields() SHARED_REQUIRES(Locks::mutator_lock_);
+  LengthPrefixedArray<ArtField>* GetSFieldsPtr() SHARED_REQUIRES(Locks::mutator_lock_);
+  ALWAYS_INLINE IterationRange<StrideIterator<ArtField>> GetSFields()
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
-  void SetSFields(ArtField* new_sfields) SHARED_REQUIRES(Locks::mutator_lock_);
+  void SetSFieldsPtr(LengthPrefixedArray<ArtField>* new_sfields)
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Unchecked edition has no verification flags.
-  void SetSFieldsUnchecked(ArtField* new_sfields) SHARED_REQUIRES(Locks::mutator_lock_);
+  void SetSFieldsPtrUnchecked(LengthPrefixedArray<ArtField>* new_sfields)
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
-  uint32_t NumStaticFields() SHARED_REQUIRES(Locks::mutator_lock_) {
-    return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_static_fields_));
-  }
-
-  void SetNumStaticFields(uint32_t num) SHARED_REQUIRES(Locks::mutator_lock_) {
-    return SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_static_fields_), num);
-  }
+  uint32_t NumStaticFields() SHARED_REQUIRES(Locks::mutator_lock_);
 
   // TODO: uint16_t
   ArtField* GetStaticField(uint32_t i) SHARED_REQUIRES(Locks::mutator_lock_);
@@ -1129,10 +1104,10 @@
     return pointer_size;
   }
 
-  ALWAYS_INLINE ArtMethod* GetDirectMethodsPtrUnchecked()
+  ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetDirectMethodsPtrUnchecked()
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  ALWAYS_INLINE ArtMethod* GetVirtualMethodsPtrUnchecked()
+  ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetVirtualMethodsPtrUnchecked()
       SHARED_REQUIRES(Locks::mutator_lock_);
 
  private:
@@ -1154,8 +1129,12 @@
   void CheckObjectAlloc() SHARED_REQUIRES(Locks::mutator_lock_);
 
   // Unchecked editions is for root visiting.
-  ArtField* GetSFieldsUnchecked() SHARED_REQUIRES(Locks::mutator_lock_);
-  ArtField* GetIFieldsUnchecked() SHARED_REQUIRES(Locks::mutator_lock_);
+  LengthPrefixedArray<ArtField>* GetSFieldsPtrUnchecked() SHARED_REQUIRES(Locks::mutator_lock_);
+  IterationRange<StrideIterator<ArtField>> GetSFieldsUnchecked()
+      SHARED_REQUIRES(Locks::mutator_lock_);
+  LengthPrefixedArray<ArtField>* GetIFieldsPtrUnchecked() SHARED_REQUIRES(Locks::mutator_lock_);
+  IterationRange<StrideIterator<ArtField>> GetIFieldsUnchecked()
+      SHARED_REQUIRES(Locks::mutator_lock_);
 
   bool ProxyDescriptorEquals(const char* match) SHARED_REQUIRES(Locks::mutator_lock_);
 
@@ -1216,7 +1195,7 @@
   // Note: Shuffled back.
   uint32_t access_flags_;
 
-  // static, private, and <init> methods. Pointer to an ArtMethod array.
+  // static, private, and <init> methods. Pointer to an ArtMethod length-prefixed array.
   uint64_t direct_methods_;
 
   // instance fields
@@ -1229,10 +1208,11 @@
   // ArtField arrays are allocated as an array of fields, and not an array of fields pointers.
   uint64_t ifields_;
 
-  // Static fields
+  // Static fields length-prefixed array.
   uint64_t sfields_;
 
-  // Virtual methods defined in this class; invoked through vtable. Pointer to an ArtMethod array.
+  // Virtual methods defined in this class; invoked through vtable. Pointer to an ArtMethod
+  // length-prefixed array.
   uint64_t virtual_methods_;
 
   // Total size of the Class instance; used when allocating storage on gc heap.
@@ -1250,24 +1230,12 @@
   // TODO: really 16bits
   int32_t dex_type_idx_;
 
-  // Number of direct fields.
-  uint32_t num_direct_methods_;
-
-  // Number of instance fields.
-  uint32_t num_instance_fields_;
-
   // Number of instance fields that are object refs.
   uint32_t num_reference_instance_fields_;
 
   // Number of static fields that are object refs,
   uint32_t num_reference_static_fields_;
 
-  // Number of static fields.
-  uint32_t num_static_fields_;
-
-  // Number of virtual methods.
-  uint32_t num_virtual_methods_;
-
   // Total object size; used when allocating storage on gc heap.
   // (For interfaces and abstract classes this will be zero.)
   // See also class_size_.
diff --git a/runtime/mirror/field.cc b/runtime/mirror/field.cc
index 02e4484..ff6847c 100644
--- a/runtime/mirror/field.cc
+++ b/runtime/mirror/field.cc
@@ -61,10 +61,10 @@
     DCHECK_EQ(declaring_class->NumStaticFields(), 2U);
     // 0 == Class[] interfaces; 1 == Class[][] throws;
     if (GetDexFieldIndex() == 0) {
-      return &declaring_class->GetSFields()[0];
+      return &declaring_class->GetSFieldsPtr()->At(0);
     } else {
       DCHECK_EQ(GetDexFieldIndex(), 1U);
-      return &declaring_class->GetSFields()[1];
+      return &declaring_class->GetSFieldsPtr()->At(1);
     }
   }
   mirror::DexCache* const dex_cache = declaring_class->GetDexCache();
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index 80decaa..87fb5ba 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -208,15 +208,13 @@
     return;
   }
   for (Class* cur = c; cur != nullptr; cur = cur->GetSuperClass()) {
-    ArtField* fields = cur->GetIFields();
-    for (size_t i = 0, count = cur->NumInstanceFields(); i < count; ++i) {
+    for (ArtField& field : cur->GetIFields()) {
       StackHandleScope<1> hs(Thread::Current());
       Handle<Object> h_object(hs.NewHandle(new_value));
-      ArtField* field = &fields[i];
-      if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
-        CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+      if (field.GetOffset().Int32Value() == field_offset.Int32Value()) {
+        CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot);
         // TODO: resolve the field type for moving GC.
-        mirror::Class* field_type = field->GetType<!kMovingCollector>();
+        mirror::Class* field_type = field.GetType<!kMovingCollector>();
         if (field_type != nullptr) {
           CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
         }
@@ -229,13 +227,11 @@
     return;
   }
   if (IsClass()) {
-    ArtField* fields = AsClass()->GetSFields();
-    for (size_t i = 0, count = AsClass()->NumStaticFields(); i < count; ++i) {
-      ArtField* field = &fields[i];
-      if (field->GetOffset().Int32Value() == field_offset.Int32Value()) {
-        CHECK_NE(field->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
+    for (ArtField& field : AsClass()->GetSFields()) {
+      if (field.GetOffset().Int32Value() == field_offset.Int32Value()) {
+        CHECK_NE(field.GetTypeAsPrimitiveType(), Primitive::kPrimNot);
         // TODO: resolve the field type for moving GC.
-        mirror::Class* field_type = field->GetType<!kMovingCollector>();
+        mirror::Class* field_type = field.GetType<!kMovingCollector>();
         if (field_type != nullptr) {
           CHECK(field_type->IsAssignableFrom(new_value->GetClass()));
         }
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index eddb2d1..1ca98e5 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -110,20 +110,18 @@
     Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
       SHARED_REQUIRES(Locks::mutator_lock_) {
   StackHandleScope<1> hs(self);
-  auto* ifields = klass->GetIFields();
-  auto* sfields = klass->GetSFields();
-  const auto num_ifields = klass->NumInstanceFields();
-  const auto num_sfields = klass->NumStaticFields();
-  size_t array_size = num_ifields + num_sfields;
+  IterationRange<StrideIterator<ArtField>> ifields = klass->GetIFields();
+  IterationRange<StrideIterator<ArtField>> sfields = klass->GetSFields();
+  size_t array_size = klass->NumInstanceFields() + klass->NumStaticFields();
   if (public_only) {
     // Lets go subtract all the non public fields.
-    for (size_t i = 0; i < num_ifields; ++i) {
-      if (!ifields[i].IsPublic()) {
+    for (ArtField& field : ifields) {
+      if (!field.IsPublic()) {
         --array_size;
       }
     }
-    for (size_t i = 0; i < num_sfields; ++i) {
-      if (!sfields[i].IsPublic()) {
+    for (ArtField& field : sfields) {
+      if (!field.IsPublic()) {
         --array_size;
       }
     }
@@ -134,34 +132,32 @@
   if (object_array.Get() == nullptr) {
     return nullptr;
   }
-  for (size_t i = 0; i < num_ifields; ++i) {
-    auto* art_field = &ifields[i];
-    if (!public_only || art_field->IsPublic()) {
-      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
-      if (field == nullptr) {
+  for (ArtField& field : ifields) {
+    if (!public_only || field.IsPublic()) {
+      auto* reflect_field = mirror::Field::CreateFromArtField(self, &field, force_resolve);
+      if (reflect_field == nullptr) {
         if (kIsDebugBuild) {
           self->AssertPendingException();
         }
         // Maybe null due to OOME or type resolving exception.
         return nullptr;
       }
-      object_array->SetWithoutChecks<false>(array_idx++, field);
+      object_array->SetWithoutChecks<false>(array_idx++, reflect_field);
     }
   }
-  for (size_t i = 0; i < num_sfields; ++i) {
-    auto* art_field = &sfields[i];
-    if (!public_only || art_field->IsPublic()) {
-      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
-      if (field == nullptr) {
+  for (ArtField& field : sfields) {
+    if (!public_only || field.IsPublic()) {
+      auto* reflect_field = mirror::Field::CreateFromArtField(self, &field, force_resolve);
+      if (reflect_field == nullptr) {
         if (kIsDebugBuild) {
           self->AssertPendingException();
         }
         return nullptr;
       }
-      object_array->SetWithoutChecks<false>(array_idx++, field);
+      object_array->SetWithoutChecks<false>(array_idx++, reflect_field);
     }
   }
-  CHECK_EQ(array_idx, array_size);
+  DCHECK_EQ(array_idx, array_size);
   return object_array.Get();
 }
 
@@ -188,16 +184,19 @@
 // the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
 // fast.
 ALWAYS_INLINE static inline ArtField* FindFieldByName(
-    Thread* self ATTRIBUTE_UNUSED, mirror::String* name, ArtField* fields, size_t num_fields)
+    Thread* self ATTRIBUTE_UNUSED, mirror::String* name, LengthPrefixedArray<ArtField>* fields)
     SHARED_REQUIRES(Locks::mutator_lock_) {
+  if (fields == nullptr) {
+    return nullptr;
+  }
   size_t low = 0;
-  size_t high = num_fields;
+  size_t high = fields->Length();
   const uint16_t* const data = name->GetValue();
   const size_t length = name->GetLength();
   while (low < high) {
     auto mid = (low + high) / 2;
-    ArtField* const field = &fields[mid];
-    int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
+    ArtField& field = fields->At(mid);
+    int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field.GetName(), data, length);
     // Alternate approach, only a few % faster at the cost of more allocations.
     // int result = field->GetStringName(self, true)->CompareTo(name);
     if (result < 0) {
@@ -205,12 +204,12 @@
     } else if (result > 0) {
       high = mid;
     } else {
-      return field;
+      return &field;
     }
   }
   if (kIsDebugBuild) {
-    for (size_t i = 0; i < num_fields; ++i) {
-      CHECK_NE(fields[i].GetName(), name->ToModifiedUtf8());
+    for (ArtField& field : MakeIterationRangeFromLengthPrefixedArray(fields, sizeof(ArtField))) {
+      CHECK_NE(field.GetName(), name->ToModifiedUtf8());
     }
   }
   return nullptr;
@@ -219,13 +218,11 @@
 ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
     Thread* self, mirror::Class* c, mirror::String* name)
     SHARED_REQUIRES(Locks::mutator_lock_) {
-  auto* instance_fields = c->GetIFields();
-  auto* art_field = FindFieldByName(self, name, instance_fields, c->NumInstanceFields());
+  ArtField* art_field = FindFieldByName(self, name, c->GetIFieldsPtr());
   if (art_field != nullptr) {
     return mirror::Field::CreateFromArtField(self, art_field, true);
   }
-  auto* static_fields = c->GetSFields();
-  art_field = FindFieldByName(self, name, static_fields, c->NumStaticFields());
+  art_field = FindFieldByName(self, name, c->GetSFieldsPtr());
   if (art_field != nullptr) {
     return mirror::Field::CreateFromArtField(self, art_field, true);
   }
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index c33b126..bc9ba37 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -160,10 +160,9 @@
   ASSERT_TRUE(proxyClass->IsProxyClass());
   ASSERT_TRUE(proxyClass->IsInitialized());
 
-  ArtField* instance_fields = proxyClass->GetIFields();
-  EXPECT_TRUE(instance_fields == nullptr);
+  EXPECT_TRUE(proxyClass->GetIFieldsPtr() == nullptr);
 
-  ArtField* static_fields = proxyClass->GetSFields();
+  LengthPrefixedArray<ArtField>* static_fields = proxyClass->GetSFieldsPtr();
   ASSERT_TRUE(static_fields != nullptr);
   ASSERT_EQ(2u, proxyClass->NumStaticFields());
 
@@ -175,7 +174,7 @@
   ASSERT_TRUE(throwsFieldClass.Get() != nullptr);
 
   // Test "Class[] interfaces" field.
-  ArtField* field = &static_fields[0];
+  ArtField* field = &static_fields->At(0);
   EXPECT_STREQ("interfaces", field->GetName());
   EXPECT_STREQ("[Ljava/lang/Class;", field->GetTypeDescriptor());
   EXPECT_EQ(interfacesFieldClass.Get(), field->GetType<true>());
@@ -184,7 +183,7 @@
   EXPECT_FALSE(field->IsPrimitiveType());
 
   // Test "Class[][] throws" field.
-  field = &static_fields[1];
+  field = &static_fields->At(1);
   EXPECT_STREQ("throws", field->GetName());
   EXPECT_STREQ("[[Ljava/lang/Class;", field->GetTypeDescriptor());
   EXPECT_EQ(throwsFieldClass.Get(), field->GetType<true>());
@@ -215,30 +214,30 @@
   ASSERT_TRUE(proxyClass1->IsProxyClass());
   ASSERT_TRUE(proxyClass1->IsInitialized());
 
-  ArtField* static_fields0 = proxyClass0->GetSFields();
+  LengthPrefixedArray<ArtField>* static_fields0 = proxyClass0->GetSFieldsPtr();
   ASSERT_TRUE(static_fields0 != nullptr);
-  ASSERT_EQ(2u, proxyClass0->NumStaticFields());
-  ArtField* static_fields1 = proxyClass1->GetSFields();
+  ASSERT_EQ(2u, static_fields0->Length());
+  LengthPrefixedArray<ArtField>* static_fields1 = proxyClass1->GetSFieldsPtr();
   ASSERT_TRUE(static_fields1 != nullptr);
-  ASSERT_EQ(2u, proxyClass1->NumStaticFields());
+  ASSERT_EQ(2u, static_fields1->Length());
 
-  EXPECT_EQ(static_fields0[0].GetDeclaringClass(), proxyClass0.Get());
-  EXPECT_EQ(static_fields0[1].GetDeclaringClass(), proxyClass0.Get());
-  EXPECT_EQ(static_fields1[0].GetDeclaringClass(), proxyClass1.Get());
-  EXPECT_EQ(static_fields1[1].GetDeclaringClass(), proxyClass1.Get());
+  EXPECT_EQ(static_fields0->At(0).GetDeclaringClass(), proxyClass0.Get());
+  EXPECT_EQ(static_fields0->At(1).GetDeclaringClass(), proxyClass0.Get());
+  EXPECT_EQ(static_fields1->At(0).GetDeclaringClass(), proxyClass1.Get());
+  EXPECT_EQ(static_fields1->At(1).GetDeclaringClass(), proxyClass1.Get());
 
   Handle<mirror::Field> field00 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0[0], true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0->At(0), true));
   Handle<mirror::Field> field01 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0[1], true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0->At(1), true));
   Handle<mirror::Field> field10 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1[0], true));
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1->At(0), true));
   Handle<mirror::Field> field11 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1[1], true));
-  EXPECT_EQ(field00->GetArtField(), &static_fields0[0]);
-  EXPECT_EQ(field01->GetArtField(), &static_fields0[1]);
-  EXPECT_EQ(field10->GetArtField(), &static_fields1[0]);
-  EXPECT_EQ(field11->GetArtField(), &static_fields1[1]);
+      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1->At(1), true));
+  EXPECT_EQ(field00->GetArtField(), &static_fields0->At(0));
+  EXPECT_EQ(field01->GetArtField(), &static_fields0->At(1));
+  EXPECT_EQ(field10->GetArtField(), &static_fields1->At(0));
+  EXPECT_EQ(field11->GetArtField(), &static_fields1->At(1));
 }
 
 }  // namespace art
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index ee2e2c5..100d199 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -780,7 +780,7 @@
   mirror::Class* klass = o->GetClass();
   mirror::Class* src_class = nullptr;
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
-  ArtField* primitive_field = &klass->GetIFields()[0];
+  ArtField* primitive_field = &klass->GetIFieldsPtr()->At(0);
   if (klass->DescriptorEquals("Ljava/lang/Boolean;")) {
     src_class = class_linker->FindPrimitiveClass('Z');
     boxed_value.SetZ(primitive_field->GetBoolean(o));
diff --git a/runtime/stride_iterator.h b/runtime/stride_iterator.h
index d8d21aa..c69f30e 100644
--- a/runtime/stride_iterator.h
+++ b/runtime/stride_iterator.h
@@ -29,11 +29,12 @@
   StrideIterator& operator=(const StrideIterator&) = default;
   StrideIterator& operator=(StrideIterator&&) = default;
 
-  StrideIterator(uintptr_t ptr, size_t stride)
-      : ptr_(ptr), stride_(stride) {
-  }
+  StrideIterator(T* ptr, size_t stride)
+      : ptr_(reinterpret_cast<uintptr_t>(ptr)),
+        stride_(reinterpret_cast<uintptr_t>(stride)) {}
 
   bool operator==(const StrideIterator& other) const {
+    DCHECK_EQ(stride_, other.stride_);
     return ptr_ == other.ptr_;
   }
 
@@ -52,6 +53,12 @@
     return temp;
   }
 
+  StrideIterator operator+(ssize_t delta) const {
+    auto temp = *this;
+    temp.ptr_ += static_cast<ssize_t>(stride_) * delta;
+    return temp;
+  }
+
   T& operator*() const {
     return *reinterpret_cast<T*>(ptr_);
   }