Revert "Revert "Move runtime/ to ClassAccessor""

Fixed misplaced UnhideAccessFlags to be outside of a conditional
that the code item is null / not deduped. This fixes an issue
where these methods would not have had their access flags restored.

Bug: 77709234
Bug: 79758018
Bug: 91962648

This reverts commit cc7e20f9ec7b4a7a57f7196e5e8be67a727f21d3.

Test: test-art-host
Test: atest FrameworksUiServicesTests
Test: atest CtsInlineMockingTestCases

Change-Id: I7e5712cdcccef81e19ce81d26743c517b0b8a67d
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index 49ca98d..3bb9e93 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -37,30 +37,26 @@
       num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
       num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
 
-inline const uint8_t* ClassAccessor::Method::Read(const uint8_t* ptr) {
-  index_ += DecodeUnsignedLeb128(&ptr);
-  access_flags_ = DecodeUnsignedLeb128(&ptr);
-  code_off_ = DecodeUnsignedLeb128(&ptr);
-  return ptr;
+inline void ClassAccessor::Method::Read() {
+  index_ += DecodeUnsignedLeb128(&ptr_pos_);
+  access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+  code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
 }
 
-inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) {
-  index_ += DecodeUnsignedLeb128(&ptr);
-  access_flags_ = DecodeUnsignedLeb128(&ptr);
-  return ptr;
+inline void ClassAccessor::Field::Read() {
+  index_ += DecodeUnsignedLeb128(&ptr_pos_);
+  access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
 }
 
 template <typename DataType, typename Visitor>
-inline const uint8_t* ClassAccessor::VisitMembers(size_t count,
-                                                  const Visitor& visitor,
-                                                  const uint8_t* ptr,
-                                                  DataType* data) const {
+inline void ClassAccessor::VisitMembers(size_t count,
+                                        const Visitor& visitor,
+                                        DataType* data) const {
   DCHECK(data != nullptr);
   for ( ; count != 0; --count) {
-    ptr = data->Read(ptr);
+    data->Read();
     visitor(*data);
   }
-  return ptr;
 }
 
 template <typename StaticFieldVisitor,
@@ -72,15 +68,15 @@
     const InstanceFieldVisitor& instance_field_visitor,
     const DirectMethodVisitor& direct_method_visitor,
     const VirtualMethodVisitor& virtual_method_visitor) const {
-  Field field(dex_file_);
-  const uint8_t* ptr = VisitMembers(num_static_fields_, static_field_visitor, ptr_pos_, &field);
+  Field field(dex_file_, ptr_pos_);
+  VisitMembers(num_static_fields_, static_field_visitor, &field);
   field.NextSection();
-  ptr = VisitMembers(num_instance_fields_, instance_field_visitor, ptr, &field);
+  VisitMembers(num_instance_fields_, instance_field_visitor, &field);
 
-  Method method(dex_file_, /*is_static_or_direct*/ true);
-  ptr = VisitMembers(num_direct_methods_, direct_method_visitor, ptr, &method);
+  Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true);
+  VisitMembers(num_direct_methods_, direct_method_visitor, &method);
   method.NextSection();
-  ptr = VisitMembers(num_virtual_methods_, virtual_method_visitor, ptr, &method);
+  VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
 }
 
 template <typename DirectMethodVisitor,
@@ -119,23 +115,64 @@
   return dex_file_.GetCodeItem(code_off_);
 }
 
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+    ClassAccessor::GetFieldsInternal(size_t count) const {
+  return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_),
+           DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) };
+}
+
+// Return an iteration range for the first <count> methods.
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+    ClassAccessor::GetMethodsInternal(size_t count) const {
+  // Skip over the fields.
+  Field field(dex_file_, ptr_pos_);
+  VisitMembers(NumFields(), VoidFunctor(), &field);
+  // Return the iterator pair.
+  return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_),
+           DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) };
+}
+
 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields()
     const {
-  const uint32_t limit = num_static_fields_ + num_instance_fields_;
-  return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, limit, ptr_pos_),
-           DataIterator<Field>(dex_file_, limit, num_static_fields_, limit, ptr_pos_) };
+  return GetFieldsInternal(num_static_fields_ + num_instance_fields_);
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+    ClassAccessor::GetStaticFields() const {
+  return GetFieldsInternal(num_static_fields_);
+}
+
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>>
+    ClassAccessor::GetInstanceFields() const {
+  IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> fields = GetFields();
+  // Skip the static fields.
+  return { std::next(fields.begin(), NumStaticFields()), fields.end() };
 }
 
 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
     ClassAccessor::GetMethods() const {
-  // Skip over the fields.
-  Field field(dex_file_);
-  const size_t skip_count = num_static_fields_ + num_instance_fields_;
-  const uint8_t* ptr_pos = VisitMembers(skip_count, VoidFunctor(), ptr_pos_, &field);
-  // Return the iterator pair for all the methods.
-  const uint32_t limit = num_direct_methods_ + num_virtual_methods_;
-  return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, limit, ptr_pos),
-           DataIterator<Method>(dex_file_, limit, num_direct_methods_, limit, ptr_pos) };
+  return GetMethodsInternal(NumMethods());
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+    ClassAccessor::GetDirectMethods() const {
+  return GetMethodsInternal(NumDirectMethods());
+}
+
+inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
+    ClassAccessor::GetVirtualMethods() const {
+  IterationRange<DataIterator<Method>> methods = GetMethods();
+  // Skip the direct fields.
+  return { std::next(methods.begin(), NumDirectMethods()), methods.end() };
+}
+
+inline void ClassAccessor::Field::UnHideAccessFlags() const {
+  DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false);
+}
+
+inline void ClassAccessor::Method::UnHideAccessFlags() const {
+  DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true);
 }
 
 }  // namespace art
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index dda6e1c..4f0fd32 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -20,6 +20,7 @@
 #include "base/utils.h"
 #include "code_item_accessors.h"
 #include "dex_file.h"
+#include "hidden_api_access_flags.h"
 #include "invoke_type.h"
 #include "method_reference.h"
 #include "modifiers.h"
@@ -33,12 +34,18 @@
  private:
   class BaseItem {
    public:
+    explicit BaseItem(const uint8_t* ptr_pos) : ptr_pos_(ptr_pos) {}
+
     uint32_t GetIndex() const {
       return index_;
     }
 
     uint32_t GetAccessFlags() const {
-      return access_flags_;
+      return HiddenApiAccessFlags::RemoveFromDex(access_flags_);
+    }
+
+    HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const {
+      return HiddenApiAccessFlags::DecodeFromDex(access_flags_);
     }
 
     bool IsFinal() const {
@@ -46,6 +53,8 @@
     }
 
    protected:
+    // Internal data pointer for reading.
+    const uint8_t* ptr_pos_ = nullptr;
     uint32_t index_ = 0u;
     uint32_t access_flags_ = 0u;
   };
@@ -76,13 +85,18 @@
       return is_static_or_direct_;
     }
 
+    // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+    void UnHideAccessFlags() const;
+
    private:
     explicit Method(const DexFile& dex_file,
+                    const uint8_t* ptr_pos,
                     bool is_static_or_direct = true)
-        : dex_file_(dex_file),
+        : BaseItem(ptr_pos),
+          dex_file_(dex_file),
           is_static_or_direct_(is_static_or_direct) {}
 
-    const uint8_t* Read(const uint8_t* ptr);
+    void Read();
 
     InvokeType GetDirectMethodInvokeType() const {
       return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
@@ -99,6 +113,7 @@
       }
     }
 
+    // Move to virtual method section.
     void NextSection() {
       DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
       is_static_or_direct_ = false;
@@ -115,20 +130,31 @@
   // A decoded version of the field of a class_data_item.
   class Field : public BaseItem {
    public:
-    explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {}
+    explicit Field(const DexFile& dex_file,
+                   const uint8_t* ptr_pos) : BaseItem(ptr_pos), dex_file_(dex_file) {}
 
     const DexFile& GetDexFile() const {
       return dex_file_;
     }
 
-   private:
-    const uint8_t* Read(const uint8_t* ptr);
+    bool IsStatic() const {
+     return is_static_;
+    }
 
+    // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
+    void UnHideAccessFlags() const;
+
+   private:
+    void Read();
+
+    // Move to instance fields section.
     void NextSection() {
       index_ = 0u;
+      is_static_ = false;
     }
 
     const DexFile& dex_file_;
+    bool is_static_ = true;
     friend class ClassAccessor;
   };
 
@@ -144,11 +170,10 @@
                  uint32_t partition_pos,
                  uint32_t iterator_end,
                  const uint8_t* ptr_pos)
-        : data_(dex_file),
+        : data_(dex_file, ptr_pos),
           position_(position),
           partition_pos_(partition_pos),
-          iterator_end_(iterator_end),
-          ptr_pos_(ptr_pos) {
+          iterator_end_(iterator_end) {
       ReadData();
     }
 
@@ -205,8 +230,7 @@
         if (position_ == partition_pos_) {
           data_.NextSection();
         }
-        DCHECK(ptr_pos_ != nullptr);
-        ptr_pos_ = data_.Read(ptr_pos_);
+        data_.Read();
       }
     }
 
@@ -217,8 +241,6 @@
     const uint32_t partition_pos_;
     // At iterator_end_, the iterator is no longer valid.
     const uint32_t iterator_end_;
-    // Internal data pointer.
-    const uint8_t* ptr_pos_;
   };
 
   // Not explicit specifically for range-based loops.
@@ -252,9 +274,21 @@
   // Return the iteration range for all the fields.
   IterationRange<DataIterator<Field>> GetFields() const;
 
+  // Return the iteration range for all the static fields.
+  IterationRange<DataIterator<Field>> GetStaticFields() const;
+
+  // Return the iteration range for all the instance fields.
+  IterationRange<DataIterator<Field>> GetInstanceFields() const;
+
   // Return the iteration range for all the methods.
   IterationRange<DataIterator<Method>> GetMethods() const;
 
+  // Return the iteration range for the direct methods.
+  IterationRange<DataIterator<Method>> GetDirectMethods() const;
+
+  // Return the iteration range for the virtual methods.
+  IterationRange<DataIterator<Method>> GetVirtualMethods() const;
+
   uint32_t NumStaticFields() const {
     return num_static_fields_;
   }
@@ -263,6 +297,10 @@
     return num_instance_fields_;
   }
 
+  uint32_t NumFields() const {
+    return NumStaticFields() + NumInstanceFields();
+  }
+
   uint32_t NumDirectMethods() const {
     return num_direct_methods_;
   }
@@ -285,14 +323,22 @@
     return dex_file_;
   }
 
+  bool HasClassData() const {
+    return ptr_pos_ != nullptr;
+  }
+
  protected:
   // Template visitor to reduce copy paste for visiting elements.
   // No thread safety analysis since the visitor may require capabilities.
   template <typename DataType, typename Visitor>
-  const uint8_t* VisitMembers(size_t count,
-                              const Visitor& visitor,
-                              const uint8_t* ptr,
-                              DataType* data) const NO_THREAD_SAFETY_ANALYSIS;
+  void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const
+      NO_THREAD_SAFETY_ANALYSIS;
+
+  // Return an iteration range for the first <count> fields.
+  IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const;
+
+  // Return an iteration range for the first <count> methods.
+  IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const;
 
   const DexFile& dex_file_;
   const dex::TypeIndex descriptor_index_ = {};
diff --git a/libdexfile/dex/class_accessor_test.cc b/libdexfile/dex/class_accessor_test.cc
index 95380d8..d0533c1 100644
--- a/libdexfile/dex/class_accessor_test.cc
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -38,18 +38,27 @@
       auto fields = accessor.GetFields();
       auto method_it = methods.begin();
       auto field_it = fields.begin();
+      auto instance_fields = accessor.GetInstanceFields();
+      auto instance_field_it = instance_fields.begin();
       accessor.VisitFieldsAndMethods(
           // Static fields.
           [&](const ClassAccessor::Field& field) {
+            EXPECT_TRUE(field.IsStatic());
+            EXPECT_TRUE(field_it->IsStatic());
             EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
             EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
             ++field_it;
           },
           // Instance fields.
           [&](const ClassAccessor::Field& field) {
+            EXPECT_FALSE(field.IsStatic());
+            EXPECT_FALSE(field_it->IsStatic());
             EXPECT_EQ(field.GetIndex(), field_it->GetIndex());
             EXPECT_EQ(field.GetAccessFlags(), field_it->GetAccessFlags());
+            EXPECT_EQ(field.GetIndex(), instance_field_it->GetIndex());
+            EXPECT_EQ(field.GetAccessFlags(), instance_field_it->GetAccessFlags());
             ++field_it;
+            ++instance_field_it;
           },
           // Direct methods.
           [&](const ClassAccessor::Method& method) {
@@ -71,6 +80,7 @@
           });
       ASSERT_TRUE(field_it == fields.end());
       ASSERT_TRUE(method_it == methods.end());
+      ASSERT_TRUE(instance_field_it == instance_fields.end());
     }
     EXPECT_EQ(class_def_idx, dex_file->NumClassDefs());
   }
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 9de260c..f570158 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,19 +45,18 @@
 static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
 static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
 
-void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
-  uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
-  uint32_t new_flag = class_it.GetMemberAccessFlags();
-  bool is_method = class_it.IsAtMethod();
+void DexFile::UnHideAccessFlags(uint8_t* data_ptr,
+                                uint32_t new_access_flags,
+                                bool is_method) {
   // Go back 1 uleb to start.
-  data = ReverseSearchUnsignedLeb128(data);
+  data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
   if (is_method) {
     // Methods have another uleb field before the access flags
-    data = ReverseSearchUnsignedLeb128(data);
+    data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
   }
-  DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
-            new_flag);
-  UpdateUnsignedLeb128(data, new_flag);
+  DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)),
+            new_access_flags);
+  UpdateUnsignedLeb128(data_ptr, new_access_flags);
 }
 
 uint32_t DexFile::CalculateChecksum() const {
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index f1f8b50..ed21980 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -1010,8 +1010,8 @@
     return container_.get();
   }
 
-  // Changes the dex file pointed to by class_it to not have any hiddenapi flags.
-  static void UnHideAccessFlags(ClassDataItemIterator& class_it);
+  // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags.
+  static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method);
 
   inline IterationRange<ClassIterator> GetClasses() const;
 
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index fcbafe7..a660fb5 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -31,6 +31,7 @@
 
 #include "base/leb128.h"
 #include "fixed_up_dex_file.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
 #include "dex/dex_file_verifier.h"
@@ -51,14 +52,12 @@
 }
 
 static void UnhideApis(const art::DexFile& target_dex_file) {
-  for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
-    const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i));
-    if (class_data != nullptr) {
-      for (art::ClassDataItemIterator class_it(target_dex_file, class_data);
-           class_it.HasNext();
-           class_it.Next()) {
-        art::DexFile::UnHideAccessFlags(class_it);
-      }
+  for (art::ClassAccessor accessor : target_dex_file.GetClasses()) {
+    for (const art::ClassAccessor::Field& field : accessor.GetFields()) {
+      field.UnHideAccessFlags();
+    }
+    for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
+      method.UnHideAccessFlags();
     }
   }
 }
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 151c36f..4e9f3c5 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,6 +26,7 @@
 #include "class_linker-inl.h"
 #include "class_root.h"
 #include "debugger.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_exception_helpers.h"
@@ -434,28 +435,14 @@
 static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
                                                  uint16_t class_def_idx,
                                                  uint32_t method_idx) {
-  const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_idx);
-  const uint8_t* class_data = dex_file.GetClassData(class_def);
-  CHECK(class_data != nullptr);
-  ClassDataItemIterator it(dex_file, class_data);
-  it.SkipAllFields();
-  // Process methods
-  size_t class_def_method_index = 0;
-  while (it.HasNextDirectMethod()) {
-    if (it.GetMemberIndex() == method_idx) {
+  ClassAccessor accessor(dex_file, dex_file.GetClassDef(class_def_idx));
+  uint32_t class_def_method_index = 0u;
+  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+    if (method.GetIndex() == method_idx) {
       return class_def_method_index;
     }
     class_def_method_index++;
-    it.Next();
   }
-  while (it.HasNextVirtualMethod()) {
-    if (it.GetMemberIndex() == method_idx) {
-      return class_def_method_index;
-    }
-    class_def_method_index++;
-    it.Next();
-  }
-  DCHECK(!it.HasNext());
   LOG(FATAL) << "Failed to find method index " << method_idx << " in " << dex_file.GetLocation();
   UNREACHABLE();
 }
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6798796..9bb562b 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,6 +56,7 @@
 #include "compiler_callbacks.h"
 #include "debug_print.h"
 #include "debugger.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_exception_helpers.h"
@@ -2730,52 +2731,50 @@
 
 uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file,
                                                        const DexFile::ClassDef& dex_class_def) {
-  const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
   size_t num_ref = 0;
   size_t num_8 = 0;
   size_t num_16 = 0;
   size_t num_32 = 0;
   size_t num_64 = 0;
-  if (class_data != nullptr) {
-    // We allow duplicate definitions of the same field in a class_data_item
-    // but ignore the repeated indexes here, b/21868015.
-    uint32_t last_field_idx = dex::kDexNoIndex;
-    for (ClassDataItemIterator it(dex_file, class_data); it.HasNextStaticField(); it.Next()) {
-      uint32_t field_idx = it.GetMemberIndex();
-      // Ordering enforced by DexFileVerifier.
-      DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
-      if (UNLIKELY(field_idx == last_field_idx)) {
-        continue;
-      }
-      last_field_idx = field_idx;
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
-      const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
-      char c = descriptor[0];
-      switch (c) {
-        case 'L':
-        case '[':
-          num_ref++;
-          break;
-        case 'J':
-        case 'D':
-          num_64++;
-          break;
-        case 'I':
-        case 'F':
-          num_32++;
-          break;
-        case 'S':
-        case 'C':
-          num_16++;
-          break;
-        case 'B':
-        case 'Z':
-          num_8++;
-          break;
-        default:
-          LOG(FATAL) << "Unknown descriptor: " << c;
-          UNREACHABLE();
-      }
+  ClassAccessor accessor(dex_file, dex_class_def);
+  // We allow duplicate definitions of the same field in a class_data_item
+  // but ignore the repeated indexes here, b/21868015.
+  uint32_t last_field_idx = dex::kDexNoIndex;
+  for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+    uint32_t field_idx = field.GetIndex();
+    // Ordering enforced by DexFileVerifier.
+    DCHECK(last_field_idx == dex::kDexNoIndex || last_field_idx <= field_idx);
+    if (UNLIKELY(field_idx == last_field_idx)) {
+      continue;
+    }
+    last_field_idx = field_idx;
+    const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
+    const char* descriptor = dex_file.GetFieldTypeDescriptor(field_id);
+    char c = descriptor[0];
+    switch (c) {
+      case 'L':
+      case '[':
+        num_ref++;
+        break;
+      case 'J':
+      case 'D':
+        num_64++;
+        break;
+      case 'I':
+      case 'F':
+        num_32++;
+        break;
+      case 'S':
+      case 'C':
+        num_16++;
+        break;
+      case 'B':
+      case 'Z':
+        num_8++;
+        break;
+      default:
+        LOG(FATAL) << "Unknown descriptor: " << c;
+        UNREACHABLE();
     }
   }
   return mirror::Class::ComputeClassSize(false,
@@ -2873,17 +2872,15 @@
   const DexFile& dex_file = klass->GetDexFile();
   const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
   CHECK(dex_class_def != nullptr);
-  const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
+  ClassAccessor accessor(dex_file, *dex_class_def);
   // There should always be class data if there were direct methods.
-  CHECK(class_data != nullptr) << klass->PrettyDescriptor();
-  ClassDataItemIterator it(dex_file, class_data);
-  it.SkipAllFields();
+  CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
   bool has_oat_class;
   OatFile::OatClass oat_class = OatFile::FindOatClass(dex_file,
                                                       klass->GetDexClassDefIndex(),
                                                       &has_oat_class);
   // Link the code of methods skipped by LinkCode.
-  for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
+  for (size_t method_index = 0; method_index < accessor.NumDirectMethods(); ++method_index) {
     ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
     if (!method->IsStatic()) {
       // Only update static methods.
@@ -2992,17 +2989,6 @@
   klass->SetDexTypeIndex(dex_class_def.class_idx_);
 }
 
-void ClassLinker::LoadClass(Thread* self,
-                            const DexFile& dex_file,
-                            const DexFile::ClassDef& dex_class_def,
-                            Handle<mirror::Class> klass) {
-  const uint8_t* class_data = dex_file.GetClassData(dex_class_def);
-  if (class_data == nullptr) {
-    return;  // no fields or methods - for example a marker interface
-  }
-  LoadClassMembers(self, dex_file, class_data, klass);
-}
-
 LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
                                                                LinearAlloc* allocator,
                                                                size_t length) {
@@ -3061,10 +3047,15 @@
   return allocator;
 }
 
-void ClassLinker::LoadClassMembers(Thread* self,
-                                   const DexFile& dex_file,
-                                   const uint8_t* class_data,
-                                   Handle<mirror::Class> klass) {
+void ClassLinker::LoadClass(Thread* self,
+                            const DexFile& dex_file,
+                            const DexFile::ClassDef& dex_class_def,
+                            Handle<mirror::Class> klass) {
+  ClassAccessor accessor(dex_file, dex_class_def);
+  if (!accessor.HasClassData()) {
+    return;
+  }
+  Runtime* const runtime = Runtime::Current();
   {
     // Note: We cannot have thread suspension until the field and method arrays are setup or else
     // Class::VisitFieldRoots may miss some fields or methods.
@@ -3073,45 +3064,79 @@
     // We allow duplicate definitions of the same field in a class_data_item
     // but ignore the repeated indexes here, b/21868015.
     LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
-    ClassDataItemIterator it(dex_file, class_data);
     LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
                                                                 allocator,
-                                                                it.NumStaticFields());
-    size_t num_sfields = 0;
-    uint32_t last_field_idx = 0u;
-    for (; it.HasNextStaticField(); it.Next()) {
-      uint32_t field_idx = it.GetMemberIndex();
-      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->At(num_sfields));
-        ++num_sfields;
-        last_field_idx = field_idx;
-      }
-    }
-
-    // Load instance fields.
+                                                                accessor.NumStaticFields());
     LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
                                                                 allocator,
-                                                                it.NumInstanceFields());
+                                                                accessor.NumInstanceFields());
+    size_t num_sfields = 0u;
     size_t num_ifields = 0u;
-    last_field_idx = 0u;
-    for (; it.HasNextInstanceField(); it.Next()) {
-      uint32_t field_idx = it.GetMemberIndex();
-      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->At(num_ifields));
-        ++num_ifields;
-        last_field_idx = field_idx;
-      }
-    }
+    uint32_t last_static_field_idx = 0u;
+    uint32_t last_instance_field_idx = 0u;
 
-    if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
-        UNLIKELY(num_ifields != it.NumInstanceFields())) {
+    // Methods
+    bool has_oat_class = false;
+    const OatFile::OatClass oat_class = (runtime->IsStarted() && !runtime->IsAotCompiler())
+        ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
+        : OatFile::OatClass::Invalid();
+    const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
+    klass->SetMethodsPtr(
+        AllocArtMethodArray(self, allocator, accessor.NumMethods()),
+        accessor.NumDirectMethods(),
+        accessor.NumVirtualMethods());
+    size_t class_def_method_index = 0;
+    uint32_t last_dex_method_index = dex::kDexNoIndex;
+    size_t last_class_def_method_index = 0;
+
+    // Use the visitor since the ranged based loops are bit slower from seeking. Seeking to the
+    // methods needs to decode all of the fields.
+    accessor.VisitFieldsAndMethods([&](
+        const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+          uint32_t field_idx = field.GetIndex();
+          DCHECK_GE(field_idx, last_static_field_idx);  // Ordering enforced by DexFileVerifier.
+          if (num_sfields == 0 || LIKELY(field_idx > last_static_field_idx)) {
+            LoadField(field, klass, &sfields->At(num_sfields));
+            ++num_sfields;
+            last_static_field_idx = field_idx;
+          }
+        }, [&](const ClassAccessor::Field& field) REQUIRES_SHARED(Locks::mutator_lock_) {
+          uint32_t field_idx = field.GetIndex();
+          DCHECK_GE(field_idx, last_instance_field_idx);  // Ordering enforced by DexFileVerifier.
+          if (num_ifields == 0 || LIKELY(field_idx > last_instance_field_idx)) {
+            LoadField(field, klass, &ifields->At(num_ifields));
+            ++num_ifields;
+            last_instance_field_idx = field_idx;
+          }
+        }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+          ArtMethod* art_method = klass->GetDirectMethodUnchecked(class_def_method_index,
+              image_pointer_size_);
+          LoadMethod(dex_file, method, klass, art_method);
+          LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+          uint32_t it_method_index = method.GetIndex();
+          if (last_dex_method_index == it_method_index) {
+            // duplicate case
+            art_method->SetMethodIndex(last_class_def_method_index);
+          } else {
+            art_method->SetMethodIndex(class_def_method_index);
+            last_dex_method_index = it_method_index;
+            last_class_def_method_index = class_def_method_index;
+          }
+          ++class_def_method_index;
+        }, [&](const ClassAccessor::Method& method) REQUIRES_SHARED(Locks::mutator_lock_) {
+          ArtMethod* art_method = klass->GetVirtualMethodUnchecked(
+              class_def_method_index - accessor.NumDirectMethods(),
+              image_pointer_size_);
+          LoadMethod(dex_file, method, klass, art_method);
+          LinkCode(this, art_method, oat_class_ptr, class_def_method_index);
+          ++class_def_method_index;
+        });
+
+    if (UNLIKELY(num_ifields + num_sfields != accessor.NumFields())) {
       LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
-          << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
-          << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
+          << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
+          << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
+          << ")";
       // NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
       if (sfields != nullptr) {
         sfields->SetSize(num_sfields);
@@ -3125,87 +3150,49 @@
     DCHECK_EQ(klass->NumStaticFields(), num_sfields);
     klass->SetIFieldsPtr(ifields);
     DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
-    // Load methods.
-    bool has_oat_class = false;
-    const OatFile::OatClass oat_class =
-        (Runtime::Current()->IsStarted() && !Runtime::Current()->IsAotCompiler())
-            ? OatFile::FindOatClass(dex_file, klass->GetDexClassDefIndex(), &has_oat_class)
-            : OatFile::OatClass::Invalid();
-    const OatFile::OatClass* oat_class_ptr = has_oat_class ? &oat_class : nullptr;
-    klass->SetMethodsPtr(
-        AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
-        it.NumDirectMethods(),
-        it.NumVirtualMethods());
-    size_t class_def_method_index = 0;
-    uint32_t last_dex_method_index = dex::kDexNoIndex;
-    size_t last_class_def_method_index = 0;
-    // TODO These should really use the iterators.
-    for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
-      ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
-      LoadMethod(dex_file, it, klass, method);
-      LinkCode(this, method, oat_class_ptr, class_def_method_index);
-      uint32_t it_method_index = it.GetMemberIndex();
-      if (last_dex_method_index == it_method_index) {
-        // duplicate case
-        method->SetMethodIndex(last_class_def_method_index);
-      } else {
-        method->SetMethodIndex(class_def_method_index);
-        last_dex_method_index = it_method_index;
-        last_class_def_method_index = class_def_method_index;
-      }
-      class_def_method_index++;
-    }
-    for (size_t i = 0; it.HasNextVirtualMethod(); i++, it.Next()) {
-      ArtMethod* method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
-      LoadMethod(dex_file, it, klass, method);
-      DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i);
-      LinkCode(this, method, oat_class_ptr, class_def_method_index);
-      class_def_method_index++;
-    }
-    DCHECK(!it.HasNext());
   }
   // Ensure that the card is marked so that remembered sets pick up native roots.
   Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass.Get());
   self->AllowThreadSuspension();
 }
 
-void ClassLinker::LoadField(const ClassDataItemIterator& it,
+void ClassLinker::LoadField(const ClassAccessor::Field& field,
                             Handle<mirror::Class> klass,
                             ArtField* dst) {
-  const uint32_t field_idx = it.GetMemberIndex();
+  const uint32_t field_idx = field.GetIndex();
   dst->SetDexFieldIndex(field_idx);
   dst->SetDeclaringClass(klass.Get());
 
   // Get access flags from the DexFile. If this is a boot class path class,
   // also set its runtime hidden API access flags.
-  uint32_t access_flags = it.GetFieldAccessFlags();
+  uint32_t access_flags = field.GetAccessFlags();
   if (klass->IsBootStrapClassLoaded()) {
     access_flags =
-        HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+        HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
   }
   dst->SetAccessFlags(access_flags);
 }
 
 void ClassLinker::LoadMethod(const DexFile& dex_file,
-                             const ClassDataItemIterator& it,
+                             const ClassAccessor::Method& method,
                              Handle<mirror::Class> klass,
                              ArtMethod* dst) {
-  uint32_t dex_method_idx = it.GetMemberIndex();
+  const uint32_t dex_method_idx = method.GetIndex();
   const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
   const char* method_name = dex_file.StringDataByIdx(method_id.name_idx_);
 
   ScopedAssertNoThreadSuspension ants("LoadMethod");
   dst->SetDexMethodIndex(dex_method_idx);
   dst->SetDeclaringClass(klass.Get());
-  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
+  dst->SetCodeItemOffset(method.GetCodeItemOffset());
 
   // Get access flags from the DexFile. If this is a boot class path class,
   // also set its runtime hidden API access flags.
-  uint32_t access_flags = it.GetMethodAccessFlags();
+  uint32_t access_flags = method.GetAccessFlags();
 
   if (klass->IsBootStrapClassLoaded()) {
     access_flags =
-        HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
+        HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
   }
 
   if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -4772,24 +4759,29 @@
                                                                  this,
                                                                  *dex_class_def);
     const DexFile& dex_file = *dex_cache->GetDexFile();
-    const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
-    ClassDataItemIterator field_it(dex_file, class_data);
+
     if (value_it.HasNext()) {
-      DCHECK(field_it.HasNextStaticField());
+      ClassAccessor accessor(dex_file, *dex_class_def);
       CHECK(can_init_statics);
-      for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
-        ArtField* field = ResolveField(
-            field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
+      for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+        if (!value_it.HasNext()) {
+          break;
+        }
+        ArtField* art_field = ResolveField(field.GetIndex(),
+                                           dex_cache,
+                                           class_loader,
+                                           /* is_static */ true);
         if (Runtime::Current()->IsActiveTransaction()) {
-          value_it.ReadValueToField<true>(field);
+          value_it.ReadValueToField<true>(art_field);
         } else {
-          value_it.ReadValueToField<false>(field);
+          value_it.ReadValueToField<false>(art_field);
         }
         if (self->IsExceptionPending()) {
           break;
         }
-        DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
+        value_it.Next();
       }
+      DCHECK(self->IsExceptionPending() || !value_it.HasNext());
     }
   }
 
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 58ce6eb..0f76bf3 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -27,6 +27,7 @@
 #include "base/enums.h"
 #include "base/macros.h"
 #include "base/mutex.h"
+#include "dex/class_accessor.h"
 #include "dex/dex_cache_resolved_classes.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_types.h"
@@ -825,18 +826,14 @@
                  const DexFile::ClassDef& dex_class_def,
                  Handle<mirror::Class> klass)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  void LoadClassMembers(Thread* self,
-                        const DexFile& dex_file,
-                        const uint8_t* class_data,
-                        Handle<mirror::Class> klass)
-      REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst)
+  void LoadField(const ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   void LoadMethod(const DexFile& dex_file,
-                  const ClassDataItemIterator& it,
-                  Handle<mirror::Class> klass, ArtMethod* dst)
+                  const ClassAccessor::Method& method,
+                  Handle<mirror::Class> klass,
+                  ArtMethod* dst)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   void FixupStaticTrampolines(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 8aed4a8..3227c69 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -32,6 +32,7 @@
 #include "class_linker-inl.h"
 #include "common_throws.h"
 #include "debugger.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_types.h"
 #include "gc/accounting/card_table-inl.h"
@@ -573,30 +574,12 @@
     }
 
     if (kPreloadDexCachesFieldsAndMethods) {
-      for (size_t class_def_index = 0;
-           class_def_index < dex_file->NumClassDefs();
-           class_def_index++) {
-        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
-        const uint8_t* class_data = dex_file->GetClassData(class_def);
-        if (class_data == nullptr) {
-          continue;
+      for (ClassAccessor accessor : dex_file->GetClasses()) {
+        for (const ClassAccessor::Field& field : accessor.GetFields()) {
+          PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic());
         }
-        ClassDataItemIterator it(*dex_file, class_data);
-        for (; it.HasNextStaticField(); it.Next()) {
-          uint32_t field_idx = it.GetMemberIndex();
-          PreloadDexCachesResolveField(dex_cache, field_idx, true);
-        }
-        for (; it.HasNextInstanceField(); it.Next()) {
-          uint32_t field_idx = it.GetMemberIndex();
-          PreloadDexCachesResolveField(dex_cache, field_idx, false);
-        }
-        for (; it.HasNextDirectMethod(); it.Next()) {
-          uint32_t method_idx = it.GetMemberIndex();
-          PreloadDexCachesResolveMethod(dex_cache, method_idx);
-        }
-        for (; it.HasNextVirtualMethod(); it.Next()) {
-          uint32_t method_idx = it.GetMemberIndex();
-          PreloadDexCachesResolveMethod(dex_cache, method_idx);
+        for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+          PreloadDexCachesResolveMethod(dex_cache, method.GetIndex());
         }
       }
     }
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 838d7f1..32aa86d 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -28,6 +28,7 @@
 #include "base/stl_util.h"
 #include "base/unix_file/fd_file.h"
 #include "dex/art_dex_file_loader.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
 #include "dex/hidden_api_access_flags.h"
@@ -283,30 +284,25 @@
   std::unordered_set<const DexFile::CodeItem*> unquickened_code_item;
   CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin,
                                                                   quickening_info));
-  for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
-    const DexFile::ClassDef& class_def = target_dex_file.GetClassDef(i);
-    const uint8_t* class_data = target_dex_file.GetClassData(class_def);
-    if (class_data != nullptr) {
-      for (ClassDataItemIterator class_it(target_dex_file, class_data);
-           class_it.HasNext();
-           class_it.Next()) {
-        if (class_it.IsAtMethod()) {
-          const DexFile::CodeItem* code_item = class_it.GetMethodCodeItem();
-          if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
-            const uint32_t offset = accessor.GetOffset(class_it.GetMemberIndex());
-            // Offset being 0 means not quickened.
-            if (offset != 0u) {
-              ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
-              optimizer::ArtDecompileDEX(
-                  target_dex_file,
-                  *code_item,
-                  quicken_data,
-                  decompile_return_instruction);
-            }
-          }
+  for (ClassAccessor class_accessor : target_dex_file.GetClasses()) {
+    for (const ClassAccessor::Method& method : class_accessor.GetMethods()) {
+      const DexFile::CodeItem* code_item = method.GetCodeItem();
+      if (code_item != nullptr && unquickened_code_item.emplace(code_item).second) {
+        const uint32_t offset = accessor.GetOffset(method.GetIndex());
+        // Offset being 0 means not quickened.
+        if (offset != 0u) {
+          ArrayRef<const uint8_t> quicken_data = GetQuickeningInfoAt(quickening_info, offset);
+          optimizer::ArtDecompileDEX(
+              target_dex_file,
+              *code_item,
+              quicken_data,
+              decompile_return_instruction);
         }
-        DexFile::UnHideAccessFlags(class_it);
       }
+      method.UnHideAccessFlags();
+    }
+    for (const ClassAccessor::Field& field : class_accessor.GetFields()) {
+      field.UnHideAccessFlags();
     }
   }
 }
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f57f757..5961748 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -35,6 +35,7 @@
 #include "class_linker.h"
 #include "class_root.h"
 #include "compiler_callbacks.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_exception_helpers.h"
@@ -190,11 +191,6 @@
                      error);
 }
 
-template <bool kDirect>
-static bool HasNextMethod(ClassDataItemIterator* it) {
-  return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
-}
-
 static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
   static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
                     && FailureKind::kSoftFailure < FailureKind::kHardFailure,
@@ -207,80 +203,6 @@
   types |= fd.types;
 }
 
-template <bool kDirect>
-MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
-                                                          ClassLinker* linker,
-                                                          const DexFile* dex_file,
-                                                          const DexFile::ClassDef& class_def,
-                                                          ClassDataItemIterator* it,
-                                                          Handle<mirror::DexCache> dex_cache,
-                                                          Handle<mirror::ClassLoader> class_loader,
-                                                          CompilerCallbacks* callbacks,
-                                                          bool allow_soft_failures,
-                                                          HardFailLogMode log_level,
-                                                          bool need_precise_constants,
-                                                          std::string* error_string) {
-  DCHECK(it != nullptr);
-
-  MethodVerifier::FailureData failure_data;
-
-  int64_t previous_method_idx = -1;
-  while (HasNextMethod<kDirect>(it)) {
-    self->AllowThreadSuspension();
-    uint32_t method_idx = it->GetMemberIndex();
-    if (method_idx == previous_method_idx) {
-      // smali can create dex files with two encoded_methods sharing the same method_idx
-      // http://code.google.com/p/smali/issues/detail?id=119
-      it->Next();
-      continue;
-    }
-    previous_method_idx = method_idx;
-    InvokeType type = it->GetMethodInvokeType(class_def);
-    ArtMethod* method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
-        method_idx, dex_cache, class_loader, /* referrer */ nullptr, type);
-    if (method == nullptr) {
-      DCHECK(self->IsExceptionPending());
-      // We couldn't resolve the method, but continue regardless.
-      self->ClearException();
-    } else {
-      DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
-    }
-    StackHandleScope<1> hs(self);
-    std::string hard_failure_msg;
-    MethodVerifier::FailureData result = VerifyMethod(self,
-                                                      method_idx,
-                                                      dex_file,
-                                                      dex_cache,
-                                                      class_loader,
-                                                      class_def,
-                                                      it->GetMethodCodeItem(),
-                                                      method,
-                                                      it->GetMethodAccessFlags(),
-                                                      callbacks,
-                                                      allow_soft_failures,
-                                                      log_level,
-                                                      need_precise_constants,
-                                                      &hard_failure_msg);
-    if (result.kind == FailureKind::kHardFailure) {
-      if (failure_data.kind == FailureKind::kHardFailure) {
-        // If we logged an error before, we need a newline.
-        *error_string += "\n";
-      } else {
-        // If we didn't log a hard failure before, print the header of the message.
-        *error_string += "Verifier rejected class ";
-        *error_string += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
-        *error_string += ":";
-      }
-      *error_string += " ";
-      *error_string += hard_failure_msg;
-    }
-    failure_data.Merge(result);
-    it->Next();
-  }
-
-  return failure_data;
-}
-
 FailureKind MethodVerifier::VerifyClass(Thread* self,
                                         const DexFile* dex_file,
                                         Handle<mirror::DexCache> dex_cache,
@@ -300,52 +222,72 @@
     return FailureKind::kHardFailure;
   }
 
-  const uint8_t* class_data = dex_file->GetClassData(class_def);
-  if (class_data == nullptr) {
-    // empty class, probably a marker interface
-    return FailureKind::kNoFailure;
+  ClassAccessor accessor(*dex_file, class_def);
+
+  int64_t previous_method_idx[2] = { -1, -1 };
+  MethodVerifier::FailureData failure_data;
+  ClassLinker* const linker = Runtime::Current()->GetClassLinker();
+
+  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+    int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
+    self->AllowThreadSuspension();
+    const uint32_t method_idx = method.GetIndex();
+    if (method_idx == *previous_idx) {
+      // smali can create dex files with two encoded_methods sharing the same method_idx
+      // http://code.google.com/p/smali/issues/detail?id=119
+      continue;
+    }
+    *previous_idx = method_idx;
+    const InvokeType type = method.GetInvokeType(class_def.access_flags_);
+    ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+        method_idx, dex_cache, class_loader, /* referrer */ nullptr, type);
+    if (resolved_method == nullptr) {
+      DCHECK(self->IsExceptionPending());
+      // We couldn't resolve the method, but continue regardless.
+      self->ClearException();
+    } else {
+      DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
+    }
+    std::string hard_failure_msg;
+    MethodVerifier::FailureData result = VerifyMethod(self,
+                                                      method_idx,
+                                                      dex_file,
+                                                      dex_cache,
+                                                      class_loader,
+                                                      class_def,
+                                                      method.GetCodeItem(),
+                                                      resolved_method,
+                                                      method.GetAccessFlags(),
+                                                      callbacks,
+                                                      allow_soft_failures,
+                                                      log_level,
+                                                      /*need_precise_constants*/ false,
+                                                      &hard_failure_msg);
+    if (result.kind == FailureKind::kHardFailure) {
+      if (failure_data.kind == FailureKind::kHardFailure) {
+        // If we logged an error before, we need a newline.
+        *error += "\n";
+      } else {
+        // If we didn't log a hard failure before, print the header of the message.
+        *error += "Verifier rejected class ";
+        *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+        *error += ":";
+      }
+      *error += " ";
+      *error += hard_failure_msg;
+    }
+    failure_data.Merge(result);
   }
-  ClassDataItemIterator it(*dex_file, class_data);
-  it.SkipAllFields();
-  ClassLinker* linker = Runtime::Current()->GetClassLinker();
-  // Direct methods.
-  MethodVerifier::FailureData data1 = VerifyMethods<true>(self,
-                                                          linker,
-                                                          dex_file,
-                                                          class_def,
-                                                          &it,
-                                                          dex_cache,
-                                                          class_loader,
-                                                          callbacks,
-                                                          allow_soft_failures,
-                                                          log_level,
-                                                          false /* need precise constants */,
-                                                          error);
-  // Virtual methods.
-  MethodVerifier::FailureData data2 = VerifyMethods<false>(self,
-                                                           linker,
-                                                           dex_file,
-                                                           class_def,
-                                                           &it,
-                                                           dex_cache,
-                                                           class_loader,
-                                                           callbacks,
-                                                           allow_soft_failures,
-                                                           log_level,
-                                                           false /* need precise constants */,
-                                                           error);
 
-  data1.Merge(data2);
-
-  if (data1.kind == FailureKind::kNoFailure) {
+  if (failure_data.kind == FailureKind::kNoFailure) {
     return FailureKind::kNoFailure;
   } else {
-    if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
+    if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
       // Print a warning about expected slow-down. Use a string temporary to print one contiguous
       // warning.
       std::string tmp =
           StringPrintf("Class %s failed lock verification and will run slower.",
-                       PrettyDescriptor(dex_file->GetClassDescriptor(class_def)).c_str());
+                       PrettyDescriptor(accessor.GetDescriptor()).c_str());
       if (!gPrintedDxMonitorText) {
         tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
                     "and incorrect proguard optimizations.";
@@ -353,7 +295,7 @@
       }
       LOG(WARNING) << tmp;
     }
-    return data1.kind;
+    return failure_data.kind;
   }
 }
 
@@ -1924,15 +1866,11 @@
 static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) {
   const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx);
   DCHECK(class_def != nullptr);
-  const uint8_t* class_data = dex_file.GetClassData(*class_def);
-  DCHECK(class_data != nullptr);
-  ClassDataItemIterator it(dex_file, class_data);
-  it.SkipStaticFields();
-  while (it.HasNextInstanceField()) {
-    if ((it.GetFieldAccessFlags() & kAccFinal) != 0) {
-      return it.GetMemberIndex();
+  ClassAccessor accessor(dex_file, *class_def);
+  for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+    if (field.IsFinal()) {
+      return field.GetIndex();
     }
-    it.Next();
   }
   return dex::kDexNoIndex;
 }
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index ae7481c6..9890af9 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -275,23 +275,6 @@
     void Merge(const FailureData& src);
   };
 
-  // Verify all direct or virtual methods of a class. The method assumes that the iterator is
-  // positioned correctly, and the iterator will be updated.
-  template <bool kDirect>
-  static FailureData VerifyMethods(Thread* self,
-                                   ClassLinker* linker,
-                                   const DexFile* dex_file,
-                                   const DexFile::ClassDef& class_def,
-                                   ClassDataItemIterator* it,
-                                   Handle<mirror::DexCache> dex_cache,
-                                   Handle<mirror::ClassLoader> class_loader,
-                                   CompilerCallbacks* callbacks,
-                                   bool allow_soft_failures,
-                                   HardFailLogMode log_level,
-                                   bool need_precise_constants,
-                                   std::string* error_string)
-      REQUIRES_SHARED(Locks::mutator_lock_);
-
   /*
    * Perform verification on a single method.
    *