Move dexdump, dexlist, openjdkjvmti to ClassAccessor

Test: test-art-host
Bug: 79758018

Change-Id: Iecdcf81b9dd2fa5cd938579847d4934467abf813
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 060d079..f8274e2 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -1212,18 +1212,19 @@
 /*
  * Dumps a method.
  */
-static void dumpMethod(const DexFile* pDexFile, u4 idx, u4 flags,
-                       const DexFile::CodeItem* pCode, u4 codeOffset, int i) {
+static void dumpMethod(const ClassAccessor::Method& method, int i) {
   // Bail for anything private if export only requested.
+  const uint32_t flags = method.GetRawAccessFlags();
   if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
     return;
   }
 
-  const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
-  const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
-  const Signature signature = pDexFile->GetMethodSignature(pMethodId);
+  const DexFile& dex_file = method.GetDexFile();
+  const DexFile::MethodId& pMethodId = dex_file.GetMethodId(method.GetIndex());
+  const char* name = dex_file.StringDataByIdx(pMethodId.name_idx_);
+  const Signature signature = dex_file.GetMethodSignature(pMethodId);
   char* typeDescriptor = strdup(signature.ToString().c_str());
-  const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
+  const char* backDescriptor = dex_file.StringByTypeIdx(pMethodId.class_idx_);
   char* accessStr = createAccessFlagStr(flags, kAccessForMethod);
 
   if (gOptions.outputFormat == OUTPUT_PLAIN) {
@@ -1231,11 +1232,15 @@
     fprintf(gOutFile, "      name          : '%s'\n", name);
     fprintf(gOutFile, "      type          : '%s'\n", typeDescriptor);
     fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
-    if (pCode == nullptr) {
+    if (method.GetCodeItem() == nullptr) {
       fprintf(gOutFile, "      code          : (none)\n");
     } else {
       fprintf(gOutFile, "      code          -\n");
-      dumpCode(pDexFile, idx, flags, pCode, codeOffset);
+      dumpCode(&dex_file,
+               method.GetIndex(),
+               flags,
+               method.GetCodeItem(),
+               method.GetCodeItemOffset());
     }
     if (gOptions.disassemble) {
       fputc('\n', gOutFile);
@@ -1316,18 +1321,20 @@
 }
 
 /*
- * Dumps a static (class) field.
+ * Dumps a static or instance (class) field.
  */
-static void dumpSField(const DexFile* pDexFile, u4 idx, u4 flags, int i, const u1** data) {
+static void dumpField(const ClassAccessor::Field& field, int i, const u1** data = nullptr) {
   // Bail for anything private if export only requested.
+  const uint32_t flags = field.GetRawAccessFlags();
   if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
     return;
   }
 
-  const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(idx);
-  const char* name = pDexFile->StringDataByIdx(pFieldId.name_idx_);
-  const char* typeDescriptor = pDexFile->StringByTypeIdx(pFieldId.type_idx_);
-  const char* backDescriptor = pDexFile->StringByTypeIdx(pFieldId.class_idx_);
+  const DexFile& dex_file = field.GetDexFile();
+  const DexFile::FieldId& field_id = dex_file.GetFieldId(field.GetIndex());
+  const char* name = dex_file.StringDataByIdx(field_id.name_idx_);
+  const char* typeDescriptor = dex_file.StringByTypeIdx(field_id.type_idx_);
+  const char* backDescriptor = dex_file.StringByTypeIdx(field_id.class_idx_);
   char* accessStr = createAccessFlagStr(flags, kAccessForField);
 
   if (gOptions.outputFormat == OUTPUT_PLAIN) {
@@ -1337,7 +1344,7 @@
     fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
     if (data != nullptr) {
       fputs("      value         : ", gOutFile);
-      dumpEncodedValue(pDexFile, data);
+      dumpEncodedValue(&dex_file, data);
       fputs("\n", gOutFile);
     }
   } else if (gOptions.outputFormat == OUTPUT_XML) {
@@ -1353,7 +1360,7 @@
     fprintf(gOutFile, " visibility=%s\n", quotedVisibility(flags));
     if (data != nullptr) {
       fputs(" value=\"", gOutFile);
-      dumpEncodedValue(pDexFile, data);
+      dumpEncodedValue(&dex_file, data);
       fputs("\"\n", gOutFile);
     }
     fputs(">\n</field>\n", gOutFile);
@@ -1363,41 +1370,16 @@
 }
 
 /*
- * Dumps an instance field.
+ * Dumping a CFG.
  */
-static void dumpIField(const DexFile* pDexFile, u4 idx, u4 flags, int i) {
-  dumpSField(pDexFile, idx, flags, i, nullptr);
-}
-
-/*
- * Dumping a CFG. Note that this will do duplicate work. utils.h doesn't expose the code-item
- * version, so the DumpMethodCFG code will have to iterate again to find it. But dexdump is a
- * tool, so this is not performance-critical.
- */
-
-static void dumpCfg(const DexFile* dex_file,
-                    u4 dex_method_idx,
-                    const DexFile::CodeItem* code_item) {
-  if (code_item != nullptr) {
-    std::ostringstream oss;
-    DumpMethodCFG(dex_file, dex_method_idx, oss);
-    fputs(oss.str().c_str(), gOutFile);
-  }
-}
-
 static void dumpCfg(const DexFile* dex_file, int idx) {
-  const DexFile::ClassDef& class_def = dex_file->GetClassDef(idx);
-  const u1* class_data = dex_file->GetClassData(class_def);
-  if (class_data == nullptr) {  // empty class such as a marker interface?
-    return;
-  }
-  ClassDataItemIterator it(*dex_file, class_data);
-  it.SkipAllFields();
-  while (it.HasNextMethod()) {
-    dumpCfg(dex_file,
-            it.GetMemberIndex(),
-            it.GetMethodCodeItem());
-    it.Next();
+  ClassAccessor accessor(*dex_file, dex_file->GetClassDef(idx));
+  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+    if (method.GetCodeItem() != nullptr) {
+      std::ostringstream oss;
+      DumpMethodCFG(method, oss);
+      fputs(oss.str().c_str(), gOutFile);
+    }
   }
 }
 
@@ -1512,65 +1494,50 @@
   }
 
   // Fields and methods.
-  const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
-  if (pEncodedData == nullptr) {
-    if (gOptions.outputFormat == OUTPUT_PLAIN) {
-      fprintf(gOutFile, "  Static fields     -\n");
-      fprintf(gOutFile, "  Instance fields   -\n");
-      fprintf(gOutFile, "  Direct methods    -\n");
-      fprintf(gOutFile, "  Virtual methods   -\n");
-    }
-  } else {
-    ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
+  ClassAccessor accessor(*pDexFile, pClassDef);
 
-    // Prepare data for static fields.
-    const u1* sData = pDexFile->GetEncodedStaticFieldValuesArray(pClassDef);
-    const u4 sSize = sData != nullptr ? DecodeUnsignedLeb128(&sData) : 0;
+  // Prepare data for static fields.
+  const u1* sData = pDexFile->GetEncodedStaticFieldValuesArray(pClassDef);
+  const u4 sSize = sData != nullptr ? DecodeUnsignedLeb128(&sData) : 0;
 
-    // Static fields.
-    if (gOptions.outputFormat == OUTPUT_PLAIN) {
-      fprintf(gOutFile, "  Static fields     -\n");
-    }
-    for (u4 i = 0; pClassData.HasNextStaticField(); i++, pClassData.Next()) {
-      dumpSField(pDexFile,
-                 pClassData.GetMemberIndex(),
-                 pClassData.GetRawMemberAccessFlags(),
-                 i,
-                 i < sSize ? &sData : nullptr);
-    }  // for
+  // Static fields.
+  if (gOptions.outputFormat == OUTPUT_PLAIN) {
+    fprintf(gOutFile, "  Static fields     -\n");
+  }
+  uint32_t i = 0u;
+  for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
+    dumpField(field, i, i < sSize ? &sData : nullptr);
+    ++i;
+  }
 
-    // Instance fields.
-    if (gOptions.outputFormat == OUTPUT_PLAIN) {
-      fprintf(gOutFile, "  Instance fields   -\n");
-    }
-    for (u4 i = 0; pClassData.HasNextInstanceField(); i++, pClassData.Next()) {
-      dumpIField(pDexFile,
-                 pClassData.GetMemberIndex(),
-                 pClassData.GetRawMemberAccessFlags(),
-                 i);
-    }  // for
+  // Instance fields.
+  if (gOptions.outputFormat == OUTPUT_PLAIN) {
+    fprintf(gOutFile, "  Instance fields   -\n");
+  }
+  i = 0u;
+  for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+    dumpField(field, i);
+    ++i;
+  }
 
-    // Direct methods.
-    if (gOptions.outputFormat == OUTPUT_PLAIN) {
-      fprintf(gOutFile, "  Direct methods    -\n");
-    }
-    for (int i = 0; pClassData.HasNextDirectMethod(); i++, pClassData.Next()) {
-      dumpMethod(pDexFile, pClassData.GetMemberIndex(),
-                           pClassData.GetRawMemberAccessFlags(),
-                           pClassData.GetMethodCodeItem(),
-                           pClassData.GetMethodCodeItemOffset(), i);
-    }  // for
+  // Direct methods.
+  if (gOptions.outputFormat == OUTPUT_PLAIN) {
+    fprintf(gOutFile, "  Direct methods    -\n");
+  }
+  i = 0u;
+  for (const ClassAccessor::Method& method : accessor.GetDirectMethods()) {
+    dumpMethod(method, i);
+    ++i;
+  }
 
-    // Virtual methods.
-    if (gOptions.outputFormat == OUTPUT_PLAIN) {
-      fprintf(gOutFile, "  Virtual methods   -\n");
-    }
-    for (int i = 0; pClassData.HasNextVirtualMethod(); i++, pClassData.Next()) {
-      dumpMethod(pDexFile, pClassData.GetMemberIndex(),
-                           pClassData.GetRawMemberAccessFlags(),
-                           pClassData.GetMethodCodeItem(),
-                           pClassData.GetMethodCodeItemOffset(), i);
-    }  // for
+  // Virtual methods.
+  if (gOptions.outputFormat == OUTPUT_PLAIN) {
+    fprintf(gOutFile, "  Virtual methods   -\n");
+  }
+  i = 0u;
+  for (const ClassAccessor::Method& method : accessor.GetVirtualMethods()) {
+    dumpMethod(method, i);
+    ++i;
   }
 
   // End of class.
diff --git a/dexdump/dexdump_cfg.cc b/dexdump/dexdump_cfg.cc
index 7e534ed..7a0eb0e 100644
--- a/dexdump/dexdump_cfg.cc
+++ b/dexdump/dexdump_cfg.cc
@@ -25,6 +25,7 @@
 #include <set>
 #include <sstream>
 
+#include "dex/class_accessor-inl.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_exception_helpers.h"
@@ -32,15 +33,12 @@
 
 namespace art {
 
-static void dumpMethodCFGImpl(const DexFile* dex_file,
-                              uint32_t dex_method_idx,
-                              const DexFile::CodeItem* code_item,
-                              std::ostream& os) {
+void DumpMethodCFG(const ClassAccessor::Method& method, std::ostream& os) {
+  const DexFile* dex_file = &method.GetDexFile();
   os << "digraph {\n";
-  os << "  # /* " << dex_file->PrettyMethod(dex_method_idx, true) << " */\n";
+  os << "  # /* " << dex_file->PrettyMethod(method.GetIndex(), true) << " */\n";
 
-  CodeItemDataAccessor accessor(*dex_file, code_item);
-
+  CodeItemDataAccessor accessor(method.GetInstructionsAndData());
   std::set<uint32_t> dex_pc_is_branch_target;
   {
     // Go and populate.
@@ -353,42 +351,5 @@
   os << "}\n";
 }
 
-void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostream& os) {
-  // This is painful, we need to find the code item. That means finding the class, and then
-  // iterating the table.
-  if (dex_method_idx >= dex_file->NumMethodIds()) {
-    os << "Could not find method-idx.";
-    return;
-  }
-  const DexFile::MethodId& method_id = dex_file->GetMethodId(dex_method_idx);
-
-  const DexFile::ClassDef* class_def = dex_file->FindClassDef(method_id.class_idx_);
-  if (class_def == nullptr) {
-    os << "Could not find class-def.";
-    return;
-  }
-
-  const uint8_t* class_data = dex_file->GetClassData(*class_def);
-  if (class_data == nullptr) {
-    os << "No class data.";
-    return;
-  }
-
-  ClassDataItemIterator it(*dex_file, class_data);
-  it.SkipAllFields();
-
-  // Find method, and dump it.
-  while (it.HasNextMethod()) {
-    uint32_t method_idx = it.GetMemberIndex();
-    if (method_idx == dex_method_idx) {
-      dumpMethodCFGImpl(dex_file, dex_method_idx, it.GetMethodCodeItem(), os);
-      return;
-    }
-    it.Next();
-  }
-
-  // Otherwise complain.
-  os << "Something went wrong, didn't find the method in the class data.";
-}
 
 }  // namespace art
diff --git a/dexdump/dexdump_cfg.h b/dexdump/dexdump_cfg.h
index 64e5f9a..564eef6 100644
--- a/dexdump/dexdump_cfg.h
+++ b/dexdump/dexdump_cfg.h
@@ -20,11 +20,11 @@
 #include <inttypes.h>
 #include <ostream>
 
+#include "dex/class_accessor.h"
+
 namespace art {
 
-class DexFile;
-
-void DumpMethodCFG(const DexFile* dex_file, uint32_t dex_method_idx, std::ostream& os);
+void DumpMethodCFG(const ClassAccessor::Method& method, std::ostream& os);
 
 }  // namespace art
 
diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc
index 88a74de..e7eaf30 100644
--- a/dexlist/dexlist.cc
+++ b/dexlist/dexlist.cc
@@ -30,6 +30,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 
+#include "dex/class_accessor-inl.h"
 #include "dex/code_item_accessors-inl.h"
 #include "dex/dex_file-inl.h"
 #include "dex/dex_file_loader.h"
@@ -142,27 +143,21 @@
  * Runs through all direct and virtual methods in the class.
  */
 void dumpClass(const DexFile* pDexFile, u4 idx) {
-  const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
+  const DexFile::ClassDef& class_def = pDexFile->GetClassDef(idx);
 
-  const char* fileName;
-  if (!pClassDef.source_file_idx_.IsValid()) {
-    fileName = nullptr;
-  } else {
-    fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
+  const char* fileName = nullptr;
+  if (class_def.source_file_idx_.IsValid()) {
+    fileName = pDexFile->StringDataByIdx(class_def.source_file_idx_);
   }
 
-  const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
-  if (pEncodedData != nullptr) {
-    ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
-    pClassData.SkipAllFields();
-    // Direct and virtual methods.
-    for (; pClassData.HasNextMethod(); pClassData.Next()) {
-      dumpMethod(pDexFile, fileName,
-                 pClassData.GetMemberIndex(),
-                 pClassData.GetRawMemberAccessFlags(),
-                 pClassData.GetMethodCodeItem(),
-                 pClassData.GetMethodCodeItemOffset());
-    }
+  ClassAccessor accessor(*pDexFile, class_def);
+  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+    dumpMethod(pDexFile,
+               fileName,
+               method.GetIndex(),
+               method.GetRawAccessFlags(),
+               method.GetCodeItem(),
+               method.GetCodeItemOffset());
   }
 }
 
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 6af907e..5579be2 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -34,7 +34,8 @@
  private:
   class BaseItem {
    public:
-    explicit BaseItem(const uint8_t* ptr_pos) : ptr_pos_(ptr_pos) {}
+    explicit BaseItem(const DexFile& dex_file,
+                      const uint8_t* ptr_pos) : dex_file_(dex_file), ptr_pos_(ptr_pos) {}
 
     uint32_t GetIndex() const {
       return index_;
@@ -56,8 +57,13 @@
       return (GetAccessFlags() & kAccFinal) != 0;
     }
 
+    const DexFile& GetDexFile() const {
+      return dex_file_;
+    }
+
    protected:
     // Internal data pointer for reading.
+    const DexFile& dex_file_;
     const uint8_t* ptr_pos_ = nullptr;
     uint32_t index_ = 0u;
     uint32_t access_flags_ = 0u;
@@ -97,9 +103,7 @@
     explicit Method(const DexFile& dex_file,
                     const uint8_t* ptr_pos,
                     bool is_static_or_direct = true)
-        : BaseItem(ptr_pos),
-          dex_file_(dex_file),
-          is_static_or_direct_(is_static_or_direct) {}
+        : BaseItem(dex_file, ptr_pos), is_static_or_direct_(is_static_or_direct) {}
 
     void Read();
 
@@ -125,7 +129,6 @@
       index_ = 0u;
     }
 
-    const DexFile& dex_file_;
     bool is_static_or_direct_ = true;
     uint32_t code_off_ = 0u;
 
@@ -136,11 +139,7 @@
   class Field : public BaseItem {
    public:
     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_;
-    }
+                   const uint8_t* ptr_pos) : BaseItem(dex_file, ptr_pos) {}
 
     bool IsStatic() const {
      return is_static_;
@@ -158,7 +157,6 @@
       is_static_ = false;
     }
 
-    const DexFile& dex_file_;
     bool is_static_ = true;
     friend class ClassAccessor;
   };
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 4de42ac..1476880 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -45,6 +45,7 @@
 #include "class_root.h"
 #include "debugger.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/dex_file_types.h"
@@ -620,11 +621,9 @@
   art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
   DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
 
-  art::ClassDataItemIterator new_iter(*dex_file_,
-                                      dex_file_->GetClassData(dex_file_->GetClassDef(0)));
-
   // Make sure we have the same number of methods.
-  uint32_t num_new_method = new_iter.NumVirtualMethods() + new_iter.NumDirectMethods();
+  art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0));
+  uint32_t num_new_method = accessor.NumMethods();
   uint32_t num_old_method = h_klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size();
   if (num_new_method != num_old_method) {
     bool bigger = num_new_method > num_old_method;
@@ -636,13 +635,12 @@
   }
 
   // Skip all of the fields. We should have already checked this.
-  new_iter.SkipAllFields();
   // Check each of the methods. NB we don't need to specifically check for removals since the 2 dex
   // files have the same number of methods, which means there must be an equal amount of additions
-  // and removals.
-  for (; new_iter.HasNextMethod(); new_iter.Next()) {
+  // and removals. We should have already checked the fields.
+  for (const art::ClassAccessor::Method& method : accessor.GetMethods()) {
     // Get the data on the method we are searching for
-    const art::DexFile::MethodId& new_method_id = dex_file_->GetMethodId(new_iter.GetMemberIndex());
+    const art::DexFile::MethodId& new_method_id = dex_file_->GetMethodId(method.GetIndex());
     const char* new_method_name = dex_file_->GetMethodName(new_method_id);
     art::Signature new_method_signature = dex_file_->GetMethodSignature(new_method_id);
     art::ArtMethod* old_method = FindMethod(h_klass, new_method_name, new_method_signature);
@@ -659,7 +657,7 @@
     // Since direct methods have different flags than virtual ones (specifically direct methods must
     // have kAccPrivate or kAccStatic or kAccConstructor flags) we can tell if a method changes from
     // virtual to direct.
-    uint32_t new_flags = new_iter.GetMethodAccessFlags();
+    uint32_t new_flags = method.GetAccessFlags();
     if (new_flags != (old_method->GetAccessFlags() & art::kAccValidMethodFlags)) {
       RecordFailure(ERR(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED),
                     StringPrintf("method '%s' (sig: %s) had different access flags",
@@ -675,20 +673,21 @@
   art::StackHandleScope<1> hs(driver_->self_);
   art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
   DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
-  art::ClassDataItemIterator new_iter(*dex_file_,
-                                      dex_file_->GetClassData(dex_file_->GetClassDef(0)));
+  art::ClassAccessor new_accessor(*dex_file_, dex_file_->GetClassDef(0));
+
   const art::DexFile& old_dex_file = h_klass->GetDexFile();
-  art::ClassDataItemIterator old_iter(old_dex_file,
-                                      old_dex_file.GetClassData(*h_klass->GetClassDef()));
+  art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
   // Instance and static fields can be differentiated by their flags so no need to check them
   // separately.
-  while (new_iter.HasNextInstanceField() || new_iter.HasNextStaticField()) {
+  auto old_fields = old_accessor.GetFields();
+  auto old_iter = old_fields.begin();
+  for (const art::ClassAccessor::Field& new_field : new_accessor.GetFields()) {
     // Get the data on the method we are searching for
-    const art::DexFile::FieldId& new_field_id = dex_file_->GetFieldId(new_iter.GetMemberIndex());
+    const art::DexFile::FieldId& new_field_id = dex_file_->GetFieldId(new_field.GetIndex());
     const char* new_field_name = dex_file_->GetFieldName(new_field_id);
     const char* new_field_type = dex_file_->GetFieldTypeDescriptor(new_field_id);
 
-    if (!(old_iter.HasNextInstanceField() || old_iter.HasNextStaticField())) {
+    if (old_iter == old_fields.end()) {
       // We are missing the old version of this method!
       RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
                     StringPrintf("Unknown field '%s' (type: %s) added!",
@@ -697,7 +696,7 @@
       return false;
     }
 
-    const art::DexFile::FieldId& old_field_id = old_dex_file.GetFieldId(old_iter.GetMemberIndex());
+    const art::DexFile::FieldId& old_field_id = old_dex_file.GetFieldId(old_iter->GetIndex());
     const char* old_field_name = old_dex_file.GetFieldName(old_field_id);
     const char* old_field_type = old_dex_file.GetFieldTypeDescriptor(old_field_id);
 
@@ -715,7 +714,7 @@
 
     // Since static fields have different flags than instance ones (specifically static fields must
     // have the kAccStatic flag) we can tell if a field changes from static to instance.
-    if (new_iter.GetFieldAccessFlags() != old_iter.GetFieldAccessFlags()) {
+    if (new_field.GetAccessFlags() != old_iter->GetAccessFlags()) {
       RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
                     StringPrintf("Field '%s' (sig: %s) had different access flags",
                                   new_field_name,
@@ -723,16 +722,15 @@
       return false;
     }
 
-    new_iter.Next();
-    old_iter.Next();
+    ++old_iter;
   }
-  if (old_iter.HasNextInstanceField() || old_iter.HasNextStaticField()) {
+  if (old_iter != old_fields.end()) {
     RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
                   StringPrintf("field '%s' (sig: %s) is missing!",
                                 old_dex_file.GetFieldName(old_dex_file.GetFieldId(
-                                    old_iter.GetMemberIndex())),
+                                    old_iter->GetIndex())),
                                 old_dex_file.GetFieldTypeDescriptor(old_dex_file.GetFieldId(
-                                    old_iter.GetMemberIndex()))));
+                                    old_iter->GetIndex()))));
     return false;
   }
   return true;
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index b7f28f0..866a57e 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -281,8 +281,8 @@
 
   // In-place unquicken the given `dex_files` based on `quickening_info`.
   // `decompile_return_instruction` controls if RETURN_VOID_BARRIER instructions are
-  // decompiled to RETURN_VOID instructions using the slower ClassDataItemIterator
-  // instead of the faster QuickeningInfoIterator.
+  // decompiled to RETURN_VOID instructions using the slower ClassAccessor instead of the faster
+  // QuickeningInfoIterator.
   // Always unquickens using the vdex dex files as the source for quicken tables.
   void Unquicken(const std::vector<const DexFile*>& target_dex_files,
                  bool decompile_return_instruction) const;
diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc
index 5353370..fbf25b8 100644
--- a/test/983-source-transform-verify/source_transform_art.cc
+++ b/test/983-source-transform-verify/source_transform_art.cc
@@ -24,6 +24,7 @@
 
 #include "dex/code_item_accessors-inl.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/dex_instruction.h"
@@ -51,23 +52,15 @@
                                                           /*verify_checksum*/ true,
                                                           &error));
   CHECK(dex.get() != nullptr) << "Failed to verify dex: " << error;
-  for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
-    const DexFile::ClassDef& def = dex->GetClassDef(i);
-    const uint8_t* data_item = dex->GetClassData(def);
-    if (data_item == nullptr) {
-      continue;
-    }
-    for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
-      if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
-        continue;
-      }
-      for (const DexInstructionPcPair& pair :
-          art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
+
+  for (ClassAccessor accessor : dex->GetClasses()) {
+    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+      for (const DexInstructionPcPair& pair : method.GetInstructions()) {
         const Instruction& inst = pair.Inst();
         int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
         if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
             (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) {
-          LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
+          LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(method.GetIndex())
                      << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
                      << inst.DumpString(dex.get()) << std::endl;
         }