Revert "Move runtime/ to ClassAccessor"

Seems to cause 'atest CtsInlineMockingTestCases' and other tests
to fail due to sending agents dex files with hiddenapi flags still
present.

This reverts commit 2649ecf6c59a29262556aa356fbf894d49df8fe7.

Reason for revert: Seems to be causing sysui test failures, maybe

Bug: 77709234
Bug: 79758018
Bug: 91962648

Test: Tree-Hugger

(cherry picked from commit cc7e20f9ec7b4a7a57f7196e5e8be67a727f21d3)

Change-Id: I3201382c432d211c84e8c176ec060b3b27e4f1a5
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h
index 3bb9e93..49ca98d 100644
--- a/libdexfile/dex/class_accessor-inl.h
+++ b/libdexfile/dex/class_accessor-inl.h
@@ -37,26 +37,30 @@
       num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u),
       num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {}
 
-inline void ClassAccessor::Method::Read() {
-  index_ += DecodeUnsignedLeb128(&ptr_pos_);
-  access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
-  code_off_ = DecodeUnsignedLeb128(&ptr_pos_);
+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::Field::Read() {
-  index_ += DecodeUnsignedLeb128(&ptr_pos_);
-  access_flags_ = DecodeUnsignedLeb128(&ptr_pos_);
+inline const uint8_t* ClassAccessor::Field::Read(const uint8_t* ptr) {
+  index_ += DecodeUnsignedLeb128(&ptr);
+  access_flags_ = DecodeUnsignedLeb128(&ptr);
+  return ptr;
 }
 
 template <typename DataType, typename Visitor>
-inline void ClassAccessor::VisitMembers(size_t count,
-                                        const Visitor& visitor,
-                                        DataType* data) const {
+inline const uint8_t* ClassAccessor::VisitMembers(size_t count,
+                                                  const Visitor& visitor,
+                                                  const uint8_t* ptr,
+                                                  DataType* data) const {
   DCHECK(data != nullptr);
   for ( ; count != 0; --count) {
-    data->Read();
+    ptr = data->Read(ptr);
     visitor(*data);
   }
+  return ptr;
 }
 
 template <typename StaticFieldVisitor,
@@ -68,15 +72,15 @@
     const InstanceFieldVisitor& instance_field_visitor,
     const DirectMethodVisitor& direct_method_visitor,
     const VirtualMethodVisitor& virtual_method_visitor) const {
-  Field field(dex_file_, ptr_pos_);
-  VisitMembers(num_static_fields_, static_field_visitor, &field);
+  Field field(dex_file_);
+  const uint8_t* ptr = VisitMembers(num_static_fields_, static_field_visitor, ptr_pos_, &field);
   field.NextSection();
-  VisitMembers(num_instance_fields_, instance_field_visitor, &field);
+  ptr = VisitMembers(num_instance_fields_, instance_field_visitor, ptr, &field);
 
-  Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true);
-  VisitMembers(num_direct_methods_, direct_method_visitor, &method);
+  Method method(dex_file_, /*is_static_or_direct*/ true);
+  ptr = VisitMembers(num_direct_methods_, direct_method_visitor, ptr, &method);
   method.NextSection();
-  VisitMembers(num_virtual_methods_, virtual_method_visitor, &method);
+  ptr = VisitMembers(num_virtual_methods_, virtual_method_visitor, ptr, &method);
 }
 
 template <typename DirectMethodVisitor,
@@ -115,64 +119,23 @@
   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 {
-  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() };
+  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_) };
 }
 
 inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>>
     ClassAccessor::GetMethods() const {
-  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);
+  // 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) };
 }
 
 }  // namespace art
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 4f0fd32..dda6e1c 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -20,7 +20,6 @@
 #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"
@@ -34,18 +33,12 @@
  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 HiddenApiAccessFlags::RemoveFromDex(access_flags_);
-    }
-
-    HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const {
-      return HiddenApiAccessFlags::DecodeFromDex(access_flags_);
+      return access_flags_;
     }
 
     bool IsFinal() const {
@@ -53,8 +46,6 @@
     }
 
    protected:
-    // Internal data pointer for reading.
-    const uint8_t* ptr_pos_ = nullptr;
     uint32_t index_ = 0u;
     uint32_t access_flags_ = 0u;
   };
@@ -85,18 +76,13 @@
       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)
-        : BaseItem(ptr_pos),
-          dex_file_(dex_file),
+        : dex_file_(dex_file),
           is_static_or_direct_(is_static_or_direct) {}
 
-    void Read();
+    const uint8_t* Read(const uint8_t* ptr);
 
     InvokeType GetDirectMethodInvokeType() const {
       return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect;
@@ -113,7 +99,6 @@
       }
     }
 
-    // Move to virtual method section.
     void NextSection() {
       DCHECK(is_static_or_direct_) << "Already in the virtual methods section";
       is_static_or_direct_ = false;
@@ -130,31 +115,20 @@
   // A decoded version of the field of a class_data_item.
   class Field : public BaseItem {
    public:
-    explicit Field(const DexFile& dex_file,
-                   const uint8_t* ptr_pos) : BaseItem(ptr_pos), dex_file_(dex_file) {}
+    explicit Field(const DexFile& dex_file) : dex_file_(dex_file) {}
 
     const DexFile& GetDexFile() const {
       return dex_file_;
     }
 
-    bool IsStatic() const {
-     return is_static_;
-    }
-
-    // Unhide the hidden API access flags at the iterator position. TODO: Deprecate.
-    void UnHideAccessFlags() const;
-
    private:
-    void Read();
+    const uint8_t* Read(const uint8_t* ptr);
 
-    // Move to instance fields section.
     void NextSection() {
       index_ = 0u;
-      is_static_ = false;
     }
 
     const DexFile& dex_file_;
-    bool is_static_ = true;
     friend class ClassAccessor;
   };
 
@@ -170,10 +144,11 @@
                  uint32_t partition_pos,
                  uint32_t iterator_end,
                  const uint8_t* ptr_pos)
-        : data_(dex_file, ptr_pos),
+        : data_(dex_file),
           position_(position),
           partition_pos_(partition_pos),
-          iterator_end_(iterator_end) {
+          iterator_end_(iterator_end),
+          ptr_pos_(ptr_pos) {
       ReadData();
     }
 
@@ -230,7 +205,8 @@
         if (position_ == partition_pos_) {
           data_.NextSection();
         }
-        data_.Read();
+        DCHECK(ptr_pos_ != nullptr);
+        ptr_pos_ = data_.Read(ptr_pos_);
       }
     }
 
@@ -241,6 +217,8 @@
     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.
@@ -274,21 +252,9 @@
   // 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_;
   }
@@ -297,10 +263,6 @@
     return num_instance_fields_;
   }
 
-  uint32_t NumFields() const {
-    return NumStaticFields() + NumInstanceFields();
-  }
-
   uint32_t NumDirectMethods() const {
     return num_direct_methods_;
   }
@@ -323,22 +285,14 @@
     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>
-  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 uint8_t* VisitMembers(size_t count,
+                              const Visitor& visitor,
+                              const uint8_t* ptr,
+                              DataType* data) const NO_THREAD_SAFETY_ANALYSIS;
 
   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 d0533c1..95380d8 100644
--- a/libdexfile/dex/class_accessor_test.cc
+++ b/libdexfile/dex/class_accessor_test.cc
@@ -38,27 +38,18 @@
       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) {
@@ -80,7 +71,6 @@
           });
       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 f570158..9de260c 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,18 +45,19 @@
 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(uint8_t* data_ptr,
-                                uint32_t new_access_flags,
-                                bool is_method) {
+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();
   // Go back 1 uleb to start.
-  data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
+  data = ReverseSearchUnsignedLeb128(data);
   if (is_method) {
     // Methods have another uleb field before the access flags
-    data_ptr = ReverseSearchUnsignedLeb128(data_ptr);
+    data = ReverseSearchUnsignedLeb128(data);
   }
-  DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)),
-            new_access_flags);
-  UpdateUnsignedLeb128(data_ptr, new_access_flags);
+  DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
+            new_flag);
+  UpdateUnsignedLeb128(data, new_flag);
 }
 
 uint32_t DexFile::CalculateChecksum() const {
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index ed21980..f1f8b50 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -1010,8 +1010,8 @@
     return container_.get();
   }
 
-  // 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);
+  // Changes the dex file pointed to by class_it to not have any hiddenapi flags.
+  static void UnHideAccessFlags(ClassDataItemIterator& class_it);
 
   inline IterationRange<ClassIterator> GetClasses() const;
 
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index a660fb5..fcbafe7 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -31,7 +31,6 @@
 
 #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"
@@ -52,12 +51,14 @@
 }
 
 static void UnhideApis(const art::DexFile& target_dex_file) {
-  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();
+  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);
+      }
     }
   }
 }
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 4e9f3c5..151c36f 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -26,7 +26,6 @@
 #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"
@@ -435,14 +434,28 @@
 static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
                                                  uint16_t class_def_idx,
                                                  uint32_t 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) {
+  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) {
       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 531c68a..dccdff0 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -56,7 +56,6 @@
 #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"
@@ -2731,50 +2730,52 @@
 
 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;
-  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();
+  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();
+      }
     }
   }
   return mirror::Class::ComputeClassSize(false,
@@ -2872,15 +2873,17 @@
   const DexFile& dex_file = klass->GetDexFile();
   const DexFile::ClassDef* dex_class_def = klass->GetClassDef();
   CHECK(dex_class_def != nullptr);
-  ClassAccessor accessor(dex_file, *dex_class_def);
+  const uint8_t* class_data = dex_file.GetClassData(*dex_class_def);
   // There should always be class data if there were direct methods.
-  CHECK(accessor.HasClassData()) << klass->PrettyDescriptor();
+  CHECK(class_data != nullptr) << klass->PrettyDescriptor();
+  ClassDataItemIterator it(dex_file, class_data);
+  it.SkipAllFields();
   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; method_index < accessor.NumDirectMethods(); ++method_index) {
+  for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) {
     ArtMethod* method = klass->GetDirectMethod(method_index, image_pointer_size_);
     if (!method->IsStatic()) {
       // Only update static methods.
@@ -2989,6 +2992,17 @@
   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) {
@@ -3047,15 +3061,10 @@
   return allocator;
 }
 
-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();
+void ClassLinker::LoadClassMembers(Thread* self,
+                                   const DexFile& dex_file,
+                                   const uint8_t* class_data,
+                                   Handle<mirror::Class> klass) {
   {
     // Note: We cannot have thread suspension until the field and method arrays are setup or else
     // Class::VisitFieldRoots may miss some fields or methods.
@@ -3064,79 +3073,45 @@
     // 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,
-                                                                accessor.NumStaticFields());
+                                                                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.
     LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
                                                                 allocator,
-                                                                accessor.NumInstanceFields());
-    size_t num_sfields = 0u;
+                                                                it.NumInstanceFields());
     size_t num_ifields = 0u;
-    uint32_t last_static_field_idx = 0u;
-    uint32_t last_instance_field_idx = 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;
+      }
+    }
 
-    // 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())) {
+    if (UNLIKELY(num_sfields != it.NumStaticFields()) ||
+        UNLIKELY(num_ifields != it.NumInstanceFields())) {
       LOG(WARNING) << "Duplicate fields in class " << klass->PrettyDescriptor()
-          << " (unique static fields: " << num_sfields << "/" << accessor.NumStaticFields()
-          << ", unique instance fields: " << num_ifields << "/" << accessor.NumInstanceFields()
-          << ")";
+          << " (unique static fields: " << num_sfields << "/" << it.NumStaticFields()
+          << ", unique instance fields: " << num_ifields << "/" << it.NumInstanceFields() << ")";
       // NOTE: Not shrinking the over-allocated sfields/ifields, just setting size.
       if (sfields != nullptr) {
         sfields->SetSize(num_sfields);
@@ -3150,49 +3125,87 @@
     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 ClassAccessor::Field& field,
+void ClassLinker::LoadField(const ClassDataItemIterator& it,
                             Handle<mirror::Class> klass,
                             ArtField* dst) {
-  const uint32_t field_idx = field.GetIndex();
+  const uint32_t field_idx = it.GetMemberIndex();
   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 = field.GetAccessFlags();
+  uint32_t access_flags = it.GetFieldAccessFlags();
   if (klass->IsBootStrapClassLoaded()) {
     access_flags =
-        HiddenApiAccessFlags::EncodeForRuntime(access_flags, field.DecodeHiddenAccessFlags());
+        HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
   }
   dst->SetAccessFlags(access_flags);
 }
 
 void ClassLinker::LoadMethod(const DexFile& dex_file,
-                             const ClassAccessor::Method& method,
+                             const ClassDataItemIterator& it,
                              Handle<mirror::Class> klass,
                              ArtMethod* dst) {
-  const uint32_t dex_method_idx = method.GetIndex();
+  uint32_t dex_method_idx = it.GetMemberIndex();
   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(method.GetCodeItemOffset());
+  dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
 
   // 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 = method.GetAccessFlags();
+  uint32_t access_flags = it.GetMethodAccessFlags();
 
   if (klass->IsBootStrapClassLoaded()) {
     access_flags =
-        HiddenApiAccessFlags::EncodeForRuntime(access_flags, method.DecodeHiddenAccessFlags());
+        HiddenApiAccessFlags::EncodeForRuntime(access_flags, it.DecodeHiddenAccessFlags());
   }
 
   if (UNLIKELY(strcmp("finalize", method_name) == 0)) {
@@ -4759,29 +4772,24 @@
                                                                  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()) {
-      ClassAccessor accessor(dex_file, *dex_class_def);
+      DCHECK(field_it.HasNextStaticField());
       CHECK(can_init_statics);
-      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);
+      for ( ; value_it.HasNext(); value_it.Next(), field_it.Next()) {
+        ArtField* field = ResolveField(
+            field_it.GetMemberIndex(), dex_cache, class_loader, /* is_static */ true);
         if (Runtime::Current()->IsActiveTransaction()) {
-          value_it.ReadValueToField<true>(art_field);
+          value_it.ReadValueToField<true>(field);
         } else {
-          value_it.ReadValueToField<false>(art_field);
+          value_it.ReadValueToField<false>(field);
         }
         if (self->IsExceptionPending()) {
           break;
         }
-        value_it.Next();
+        DCHECK(!value_it.HasNext() || field_it.HasNextStaticField());
       }
-      DCHECK(self->IsExceptionPending() || !value_it.HasNext());
     }
   }
 
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 479d04b..32016fa 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -27,7 +27,6 @@
 #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,14 +824,18 @@
                  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 ClassAccessor::Field& field, Handle<mirror::Class> klass, ArtField* dst)
+  void LoadField(const ClassDataItemIterator& it, Handle<mirror::Class> klass, ArtField* dst)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   void LoadMethod(const DexFile& dex_file,
-                  const ClassAccessor::Method& method,
-                  Handle<mirror::Class> klass,
-                  ArtMethod* dst)
+                  const ClassDataItemIterator& it,
+                  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 145ce0d..280f99c 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -32,7 +32,6 @@
 #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"
@@ -574,12 +573,30 @@
     }
 
     if (kPreloadDexCachesFieldsAndMethods) {
-      for (ClassAccessor accessor : dex_file->GetClasses()) {
-        for (const ClassAccessor::Field& field : accessor.GetFields()) {
-          PreloadDexCachesResolveField(dex_cache, field.GetIndex(), field.IsStatic());
+      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 (const ClassAccessor::Method& method : accessor.GetMethods()) {
-          PreloadDexCachesResolveMethod(dex_cache, method.GetIndex());
+        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);
         }
       }
     }
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index e2f42c9..838d7f1 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -28,7 +28,6 @@
 #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"
@@ -284,26 +283,31 @@
   std::unordered_set<const DexFile::CodeItem*> unquickened_code_item;
   CompactOffsetTable::Accessor accessor(GetQuickenInfoOffsetTable(source_dex_begin,
                                                                   quickening_info));
-  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);
+  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);
+            }
+          }
         }
-        method.UnHideAccessFlags();
+        DexFile::UnHideAccessFlags(class_it);
       }
     }
-    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 f4967f7..2e3a659 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -35,7 +35,6 @@
 #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"
@@ -191,6 +190,11 @@
                      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,
@@ -203,6 +207,80 @@
   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,
@@ -222,72 +300,52 @@
     return FailureKind::kHardFailure;
   }
 
-  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);
+  const uint8_t* class_data = dex_file->GetClassData(class_def);
+  if (class_data == nullptr) {
+    // empty class, probably a marker interface
+    return FailureKind::kNoFailure;
   }
+  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);
 
-  if (failure_data.kind == FailureKind::kNoFailure) {
+  data1.Merge(data2);
+
+  if (data1.kind == FailureKind::kNoFailure) {
     return FailureKind::kNoFailure;
   } else {
-    if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
+    if ((data1.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(accessor.GetDescriptor()).c_str());
+                       PrettyDescriptor(dex_file->GetClassDescriptor(class_def)).c_str());
       if (!gPrintedDxMonitorText) {
         tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
                     "and incorrect proguard optimizations.";
@@ -295,7 +353,7 @@
       }
       LOG(WARNING) << tmp;
     }
-    return failure_data.kind;
+    return data1.kind;
   }
 }
 
@@ -1866,11 +1924,15 @@
 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);
-  ClassAccessor accessor(dex_file, *class_def);
-  for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
-    if (field.IsFinal()) {
-      return field.GetIndex();
+  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();
     }
+    it.Next();
   }
   return dex::kDexNoIndex;
 }
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 9890af9..ae7481c6 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -275,6 +275,23 @@
     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.
    *