Merge "Cleanup BitMemoryReader/Writer api."
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index a881c5e..3fc559e 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -88,7 +88,7 @@
 JitCompiler::JitCompiler() {
   compiler_options_.reset(new CompilerOptions());
   // Special case max code units for inlining, whose default is "unset" (implictly
-  // meaning no limit). Do this before parsing the actuall passed options.
+  // meaning no limit). Do this before parsing the actual passed options.
   compiler_options_->SetInlineMaxCodeUnits(CompilerOptions::kDefaultInlineMaxCodeUnits);
   {
     std::string error_msg;
diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h
index 8ffeee4..d40577f 100644
--- a/libdexfile/dex/class_accessor.h
+++ b/libdexfile/dex/class_accessor.h
@@ -31,7 +31,7 @@
 
 // Classes to access Dex data.
 class ClassAccessor {
- private:
+ public:
   class BaseItem {
    public:
     explicit BaseItem(const DexFile& dex_file,
@@ -65,6 +65,14 @@
       return ptr_pos_;
     }
 
+    bool MemberIsNative() const {
+      return GetRawAccessFlags() & kAccNative;
+    }
+
+    bool MemberIsFinal() const {
+      return GetRawAccessFlags() & kAccFinal;
+    }
+
    protected:
     // Internal data pointer for reading.
     const DexFile& dex_file_;
@@ -73,7 +81,6 @@
     uint32_t access_flags_ = 0u;
   };
 
- public:
   // A decoded version of the method of a class_data_item.
   class Method : public BaseItem {
    public:
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 1476880..dd0428d 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -368,17 +368,6 @@
     if (res != OK) {
       return res;
     }
-    // We make a copy of the class_bytes to pass into the retransformation.
-    // This makes cleanup easier (since we unambiguously own the bytes) and also is useful since we
-    // will need to keep the original bytes around unaltered for subsequent RetransformClasses calls
-    // to get the passed in bytes.
-    unsigned char* class_bytes_copy = nullptr;
-    res = env->Allocate(definitions[i].class_byte_count, &class_bytes_copy);
-    if (res != OK) {
-      return res;
-    }
-    memcpy(class_bytes_copy, definitions[i].class_bytes, definitions[i].class_byte_count);
-
     ArtClassDefinition def;
     res = def.Init(self, definitions[i]);
     if (res != OK) {
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index edaa043..b03f671 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -53,9 +53,9 @@
 // If kFilterModUnionCards then we attempt to filter cards that don't need to be dirty in the mod
 // union table. Disabled since it does not seem to help the pause much.
 static constexpr bool kFilterModUnionCards = kIsDebugBuild;
-// If kDisallowReadBarrierDuringScan is true then the GC aborts if there are any that occur during
-// ConcurrentCopying::Scan. May be used to diagnose possibly unnecessary read barriers.
-// Only enabled for kIsDebugBuild to avoid performance hit.
+// If kDisallowReadBarrierDuringScan is true then the GC aborts if there are any read barrier that
+// occur during ConcurrentCopying::Scan in GC thread. May be used to diagnose possibly unnecessary
+// read barriers. Only enabled for kIsDebugBuild to avoid performance hit.
 static constexpr bool kDisallowReadBarrierDuringScan = kIsDebugBuild;
 // Slow path mark stack size, increase this if the stack is getting full and it is causing
 // performance problems.
diff --git a/runtime/gc/space/malloc_space.cc b/runtime/gc/space/malloc_space.cc
index 0965560..6936fdc 100644
--- a/runtime/gc/space/malloc_space.cc
+++ b/runtime/gc/space/malloc_space.cc
@@ -247,7 +247,7 @@
     }
   }
   // Use a bulk free, that merges consecutive objects before freeing or free per object?
-  // Documentation suggests better free performance with merging, but this may be at the expensive
+  // Documentation suggests better free performance with merging, but this may be at the expense
   // of allocation.
   context->freed.objects += num_ptrs;
   context->freed.bytes += space->FreeList(self, num_ptrs, ptrs);
diff --git a/runtime/gc/space/region_space.cc b/runtime/gc/space/region_space.cc
index 0701330..0569092 100644
--- a/runtime/gc/space/region_space.cc
+++ b/runtime/gc/space/region_space.cc
@@ -16,6 +16,7 @@
 
 #include "bump_pointer_space-inl.h"
 #include "bump_pointer_space.h"
+#include "base/dumpable.h"
 #include "gc/accounting/read_barrier_table.h"
 #include "mirror/class-inl.h"
 #include "mirror/object-inl.h"
@@ -42,6 +43,9 @@
 // points to a valid, non-protected memory area.
 static constexpr uint32_t kPoisonDeadObject = 0xBADDB01D;  // "BADDROID"
 
+// Whether we check a region's live bytes count against the region bitmap.
+static constexpr bool kCheckLiveBytesAgainstRegionBitmap = kIsDebugBuild;
+
 MemMap* RegionSpace::CreateMemMap(const std::string& name, size_t capacity,
                                   uint8_t* requested_begin) {
   CHECK_ALIGNED(capacity, kRegionSize);
@@ -316,6 +320,9 @@
   };
   for (size_t i = 0; i < std::min(num_regions_, non_free_region_index_limit_); ++i) {
     Region* r = &regions_[i];
+    if (kCheckLiveBytesAgainstRegionBitmap) {
+      CheckLiveBytesAgainstRegionBitmap(r);
+    }
     if (r->IsInFromSpace()) {
       *cleared_bytes += r->BytesAllocated();
       *cleared_objects += r->ObjectsAllocated();
@@ -404,6 +411,42 @@
   num_evac_regions_ = 0;
 }
 
+void RegionSpace::CheckLiveBytesAgainstRegionBitmap(Region* r) {
+  if (r->LiveBytes() == static_cast<size_t>(-1)) {
+    // Live bytes count is undefined for `r`; nothing to check here.
+    return;
+  }
+
+  // Functor walking the region space bitmap for the range corresponding
+  // to region `r` and calculating the sum of live bytes.
+  size_t live_bytes_recount = 0u;
+  auto recount_live_bytes =
+      [&r, &live_bytes_recount](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+    DCHECK_ALIGNED(obj, kAlignment);
+    if (r->IsLarge()) {
+      // If `r` is a large region, then it contains at most one
+      // object, which must start at the beginning of the
+      // region. The live byte count in that case is equal to the
+      // allocated regions (large region + large tails regions).
+      DCHECK_EQ(reinterpret_cast<uint8_t*>(obj), r->Begin());
+      DCHECK_EQ(live_bytes_recount, 0u);
+      live_bytes_recount = r->Top() - r->Begin();
+    } else {
+      DCHECK(r->IsAllocated())
+          << "r->State()=" << r->State() << " r->LiveBytes()=" << r->LiveBytes();
+      size_t obj_size = obj->SizeOf<kDefaultVerifyFlags>();
+      size_t alloc_size = RoundUp(obj_size, space::RegionSpace::kAlignment);
+      live_bytes_recount += alloc_size;
+    }
+  };
+  // Visit live objects in `r` and recount the live bytes.
+  GetLiveBitmap()->VisitMarkedRange(reinterpret_cast<uintptr_t>(r->Begin()),
+                                    reinterpret_cast<uintptr_t>(r->Top()),
+                                    recount_live_bytes);
+  // Check that this recount matches the region's current live bytes count.
+  DCHECK_EQ(live_bytes_recount, r->LiveBytes());
+}
+
 // Poison the memory area in range [`begin`, `end`) with value `kPoisonDeadObject`.
 static void PoisonUnevacuatedRange(uint8_t* begin, uint8_t* end) {
   static constexpr size_t kPoisonDeadObjectSize = sizeof(kPoisonDeadObject);
@@ -423,7 +466,8 @@
   // The live byte count of `r` should be different from -1, as this
   // region should neither be a newly allocated region nor an
   // evacuated region.
-  DCHECK_NE(r->LiveBytes(), static_cast<size_t>(-1));
+  DCHECK_NE(r->LiveBytes(), static_cast<size_t>(-1))
+      << "Unexpected live bytes count of -1 in " << Dumpable<Region>(*r);
 
   // Past-the-end address of the previously visited (live) object (or
   // the beginning of the region, if `maybe_poison` has not run yet).
diff --git a/runtime/gc/space/region_space.h b/runtime/gc/space/region_space.h
index fa33a8a..90f1f1d 100644
--- a/runtime/gc/space/region_space.h
+++ b/runtime/gc/space/region_space.h
@@ -602,6 +602,11 @@
                                     /* out */ size_t* bytes_tl_bulk_allocated,
                                     /* out */ size_t* next_region = nullptr) REQUIRES(region_lock_);
 
+  // Check that the value of `r->LiveBytes()` matches the number of
+  // (allocated) bytes used by live objects according to the live bits
+  // in the region space bitmap range corresponding to region `r`.
+  void CheckLiveBytesAgainstRegionBitmap(Region* r);
+
   // Poison memory areas used by dead objects within unevacuated
   // region `r`. This is meant to detect dangling references to dead
   // objects earlier in debug mode.
diff --git a/tools/hiddenapi/hiddenapi.cc b/tools/hiddenapi/hiddenapi.cc
index e4bec06..bf8a1b7 100644
--- a/tools/hiddenapi/hiddenapi.cc
+++ b/tools/hiddenapi/hiddenapi.cc
@@ -26,6 +26,7 @@
 #include "base/os.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-inl.h"
 #include "dex/hidden_api_access_flags.h"
 
@@ -91,32 +92,23 @@
   return std::find(vec.begin(), vec.end(), elem) != vec.end();
 }
 
-class DexClass {
+class DexClass : public ClassAccessor {
  public:
-  DexClass(const DexFile& dex_file, uint32_t idx)
-      : dex_file_(dex_file), class_def_(dex_file.GetClassDef(idx)) {}
+  explicit DexClass(const ClassAccessor& accessor) : ClassAccessor(accessor) {}
 
-  const DexFile& GetDexFile() const { return dex_file_; }
-  const uint8_t* GetData() const { return dex_file_.GetClassData(class_def_); }
+  const uint8_t* GetData() const { return dex_file_.GetClassData(GetClassDef()); }
 
-  const dex::TypeIndex GetClassIndex() const { return class_def_.class_idx_; }
-  const dex::TypeIndex GetSuperclassIndex() const { return class_def_.superclass_idx_; }
+  const dex::TypeIndex GetSuperclassIndex() const { return GetClassDef().superclass_idx_; }
 
   bool HasSuperclass() const { return dex_file_.IsTypeIndexValid(GetSuperclassIndex()); }
 
-  std::string GetDescriptor() const { return dex_file_.GetClassDescriptor(class_def_); }
-
   std::string GetSuperclassDescriptor() const {
-    if (HasSuperclass()) {
-      return dex_file_.StringByTypeIdx(GetSuperclassIndex());
-    } else {
-      return "";
-    }
+    return HasSuperclass() ? dex_file_.StringByTypeIdx(GetSuperclassIndex()) : "";
   }
 
   std::set<std::string> GetInterfaceDescriptors() const {
     std::set<std::string> list;
-    const DexFile::TypeList* ifaces = dex_file_.GetInterfacesList(class_def_);
+    const DexFile::TypeList* ifaces = dex_file_.GetInterfacesList(GetClassDef());
     for (uint32_t i = 0; ifaces != nullptr && i < ifaces->Size(); ++i) {
       list.insert(dex_file_.StringByTypeIdx(ifaces->GetTypeItem(i).type_idx_));
     }
@@ -126,7 +118,7 @@
   inline bool IsPublic() const { return HasAccessFlags(kAccPublic); }
 
   inline bool Equals(const DexClass& other) const {
-    bool equals = GetDescriptor() == other.GetDescriptor();
+    bool equals = strcmp(GetDescriptor(), other.GetDescriptor()) == 0;
     if (equals) {
       // TODO(dbrazdil): Check that methods/fields match as well once b/111116543 is fixed.
       CHECK_EQ(GetAccessFlags(), other.GetAccessFlags());
@@ -137,39 +129,40 @@
   }
 
  private:
-  uint32_t GetAccessFlags() const { return class_def_.access_flags_; }
+  uint32_t GetAccessFlags() const { return GetClassDef().access_flags_; }
   bool HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; }
-
-  const DexFile& dex_file_;
-  const DexFile::ClassDef& class_def_;
 };
 
 class DexMember {
  public:
-  DexMember(const DexClass& klass, const ClassDataItemIterator& it)
-      : klass_(klass), it_(it) {
-    DCHECK_EQ(IsMethod() ? GetMethodId().class_idx_ : GetFieldId().class_idx_,
-              klass_.GetClassIndex());
+  DexMember(const DexClass& klass, const ClassAccessor::Field& item)
+      : klass_(klass), item_(item), is_method_(false) {
+    DCHECK_EQ(GetFieldId().class_idx_, klass.GetClassIdx());
+  }
+
+  DexMember(const DexClass& klass, const ClassAccessor::Method& item)
+      : klass_(klass), item_(item), is_method_(true) {
+    DCHECK_EQ(GetMethodId().class_idx_, klass.GetClassIdx());
   }
 
   inline const DexClass& GetDeclaringClass() const { return klass_; }
 
   // Sets hidden bits in access flags and writes them back into the DEX in memory.
-  // Note that this will not update the cached data of ClassDataItemIterator
+  // Note that this will not update the cached data of the class accessor
   // until it iterates over this item again and therefore will fail a CHECK if
   // it is called multiple times on the same DexMember.
-  void SetHidden(HiddenApiAccessFlags::ApiList value) {
-    const uint32_t old_flags = it_.GetRawMemberAccessFlags();
+  void SetHidden(HiddenApiAccessFlags::ApiList value) const {
+    const uint32_t old_flags = item_.GetRawAccessFlags();
     const uint32_t new_flags = HiddenApiAccessFlags::EncodeForDex(old_flags, value);
     CHECK_EQ(UnsignedLeb128Size(new_flags), UnsignedLeb128Size(old_flags));
 
     // Locate the LEB128-encoded access flags in class data.
     // `ptr` initially points to the next ClassData item. We iterate backwards
     // until we hit the terminating byte of the previous Leb128 value.
-    const uint8_t* ptr = it_.DataPointer();
+    const uint8_t* ptr = item_.GetDataPointer();
     if (IsMethod()) {
       ptr = ReverseSearchUnsignedLeb128(ptr);
-      DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), it_.GetMethodCodeItemOffset());
+      DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), GetMethod().GetCodeItemOffset());
     }
     ptr = ReverseSearchUnsignedLeb128(ptr);
     DCHECK_EQ(DecodeUnsignedLeb128WithoutMovingCursor(ptr), old_flags);
@@ -178,8 +171,8 @@
     UpdateUnsignedLeb128(const_cast<uint8_t*>(ptr), new_flags);
   }
 
-  inline bool IsMethod() const { return it_.IsAtMethod(); }
-  inline bool IsVirtualMethod() const { return it_.IsAtVirtualMethod(); }
+  inline bool IsMethod() const { return is_method_; }
+  inline bool IsVirtualMethod() const { return IsMethod() && !GetMethod().IsStaticOrDirect(); }
   inline bool IsConstructor() const { return IsMethod() && HasAccessFlags(kAccConstructor); }
 
   inline bool IsPublicOrProtected() const {
@@ -189,11 +182,12 @@
   // Constructs a string with a unique signature of this class member.
   std::string GetApiEntry() const {
     std::stringstream ss;
-    ss << klass_.GetDescriptor() << "->" << GetName() << (IsMethod() ? "" : ":") << GetSignature();
+    ss << klass_.GetDescriptor() << "->" << GetName() << (IsMethod() ? "" : ":")
+       << GetSignature();
     return ss.str();
   }
 
-  inline bool operator==(const DexMember& other) {
+  inline bool operator==(const DexMember& other) const {
     // These need to match if they should resolve to one another.
     bool equals = IsMethod() == other.IsMethod() &&
                   GetName() == other.GetName() &&
@@ -208,31 +202,37 @@
   }
 
  private:
-  inline uint32_t GetAccessFlags() const { return it_.GetMemberAccessFlags(); }
+  inline uint32_t GetAccessFlags() const { return item_.GetAccessFlags(); }
   inline uint32_t HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; }
 
   inline std::string GetName() const {
-    return IsMethod() ? klass_.GetDexFile().GetMethodName(GetMethodId())
-                      : klass_.GetDexFile().GetFieldName(GetFieldId());
+    return IsMethod() ? item_.GetDexFile().GetMethodName(GetMethodId())
+                      : item_.GetDexFile().GetFieldName(GetFieldId());
   }
 
   inline std::string GetSignature() const {
-    return IsMethod() ? klass_.GetDexFile().GetMethodSignature(GetMethodId()).ToString()
-                      : klass_.GetDexFile().GetFieldTypeDescriptor(GetFieldId());
+    return IsMethod() ? item_.GetDexFile().GetMethodSignature(GetMethodId()).ToString()
+                      : item_.GetDexFile().GetFieldTypeDescriptor(GetFieldId());
+  }
+
+  inline const ClassAccessor::Method& GetMethod() const {
+    DCHECK(IsMethod());
+    return down_cast<const ClassAccessor::Method&>(item_);
   }
 
   inline const DexFile::MethodId& GetMethodId() const {
     DCHECK(IsMethod());
-    return klass_.GetDexFile().GetMethodId(it_.GetMemberIndex());
+    return item_.GetDexFile().GetMethodId(item_.GetIndex());
   }
 
   inline const DexFile::FieldId& GetFieldId() const {
     DCHECK(!IsMethod());
-    return klass_.GetDexFile().GetFieldId(it_.GetMemberIndex());
+    return item_.GetDexFile().GetFieldId(item_.GetIndex());
   }
 
   const DexClass& klass_;
-  const ClassDataItemIterator& it_;
+  const ClassAccessor::BaseItem& item_;
+  const bool is_method_;
 };
 
 class ClassPath FINAL {
@@ -244,22 +244,20 @@
   template<typename Fn>
   void ForEachDexClass(Fn fn) {
     for (auto& dex_file : dex_files_) {
-      for (uint32_t class_idx = 0; class_idx < dex_file->NumClassDefs(); ++class_idx) {
-        DexClass klass(*dex_file, class_idx);
-        fn(klass);
+      for (ClassAccessor accessor : dex_file->GetClasses()) {
+        fn(DexClass(accessor));
       }
     }
   }
 
   template<typename Fn>
   void ForEachDexMember(Fn fn) {
-    ForEachDexClass([&fn](DexClass& klass) {
-      const uint8_t* klass_data = klass.GetData();
-      if (klass_data != nullptr) {
-        for (ClassDataItemIterator it(klass.GetDexFile(), klass_data); it.HasNext(); it.Next()) {
-          DexMember member(klass, it);
-          fn(member);
-        }
+    ForEachDexClass([&fn](const DexClass& klass) {
+      for (const ClassAccessor::Field& field : klass.GetFields()) {
+        fn(DexMember(klass, field));
+      }
+      for (const ClassAccessor::Method& method : klass.GetMethods()) {
+        fn(DexMember(klass, method));
       }
     });
   }
@@ -416,16 +414,18 @@
   template<typename Fn>
   ResolutionResult ForEachMatchingMember(const DexMember& other, Fn fn) {
     ResolutionResult found = ResolutionResult::kNotFound;
+    auto compare_member = [&](const DexMember& member) {
+      if (member == other) {
+        found = Accumulate(found, fn(member) ? ResolutionResult::kFoundNew
+                                             : ResolutionResult::kFoundOld);
+      }
+    };
     for (const DexClass& dex_class : dex_classes_) {
-      const uint8_t* data = dex_class.GetData();
-      if (data != nullptr) {
-        for (ClassDataItemIterator it(dex_class.GetDexFile(), data); it.HasNext(); it.Next()) {
-          DexMember member(dex_class, it);
-          if (member == other) {
-            found = Accumulate(found, fn(member) ? ResolutionResult::kFoundNew
-                                                 : ResolutionResult::kFoundOld);
-          }
-        }
+      for (const ClassAccessor::Field& field : dex_class.GetFields()) {
+        compare_member(DexMember(dex_class, field));
+      }
+      for (const ClassAccessor::Method& method : dex_class.GetMethods()) {
+        compare_member(DexMember(dex_class, method));
       }
     }
     return found;
@@ -528,7 +528,7 @@
   void BuildClassHierarchy() {
     // Create one HierarchyClass entry in `classes_` per class descriptor
     // and add all DexClass objects with the same descriptor to that entry.
-    classpath_.ForEachDexClass([this](DexClass& klass) {
+    classpath_.ForEachDexClass([this](const DexClass& klass) {
       classes_[klass.GetDescriptor()].AddDexClass(klass);
     });
 
@@ -643,13 +643,9 @@
     ClassPath boot_classpath(boot_dex_paths_, /* open_writable */ true);
 
     // Set access flags of all members.
-    boot_classpath.ForEachDexMember([&api_list](DexMember& boot_member) {
+    boot_classpath.ForEachDexMember([&api_list](const DexMember& boot_member) {
       auto it = api_list.find(boot_member.GetApiEntry());
-      if (it == api_list.end()) {
-        boot_member.SetHidden(HiddenApiAccessFlags::kWhitelist);
-      } else {
-        boot_member.SetHidden(it->second);
-      }
+      boot_member.SetHidden(it == api_list.end() ? HiddenApiAccessFlags::kWhitelist : it->second);
     });
 
     boot_classpath.UpdateDexChecksums();
@@ -696,7 +692,7 @@
     Hierarchy boot_hierarchy(boot_classpath);
 
     // Mark all boot dex members private.
-    boot_classpath.ForEachDexMember([&boot_members](DexMember& boot_member) {
+    boot_classpath.ForEachDexMember([&boot_members](const DexMember& boot_member) {
       boot_members[boot_member.GetApiEntry()] = false;
     });
 
@@ -705,14 +701,15 @@
       ClassPath stub_classpath(stub_classpath_dex, /* open_writable */ false);
       Hierarchy stub_hierarchy(stub_classpath);
       stub_classpath.ForEachDexMember(
-          [&stub_hierarchy, &boot_hierarchy, &boot_members, &unresolved](DexMember& stub_member) {
+          [&stub_hierarchy, &boot_hierarchy, &boot_members, &unresolved](
+              const DexMember& stub_member) {
             if (!stub_hierarchy.IsMemberVisible(stub_member)) {
               // Typically fake constructors and inner-class `this` fields.
               return;
             }
             bool resolved = boot_hierarchy.ForEachResolvableMember(
                 stub_member,
-                [&boot_members](DexMember& boot_member) {
+                [&boot_members](const DexMember& boot_member) {
                   std::string entry = boot_member.GetApiEntry();
                   auto it = boot_members.find(entry);
                   CHECK(it != boot_members.end());
diff --git a/tools/hiddenapi/hiddenapi_test.cc b/tools/hiddenapi/hiddenapi_test.cc
index aa87f21..b50f684 100644
--- a/tools/hiddenapi/hiddenapi_test.cc
+++ b/tools/hiddenapi/hiddenapi_test.cc
@@ -20,6 +20,7 @@
 #include "base/zip_archive.h"
 #include "common_runtime_test.h"
 #include "dex/art_dex_file_loader.h"
+#include "dex/class_accessor-inl.h"
 #include "dex/dex_file-inl.h"
 #include "exec_utils.h"
 
@@ -114,40 +115,27 @@
   }
 
   const DexFile::ClassDef& FindClass(const char* desc, const DexFile& dex_file) {
-    for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
-      const DexFile::ClassDef& class_def = dex_file.GetClassDef(i);
-      if (strcmp(desc, dex_file.GetClassDescriptor(class_def)) == 0) {
-        return class_def;
-      }
-    }
-    LOG(FATAL) << "Could not find class " << desc;
-    UNREACHABLE();
+    const DexFile::TypeId* type_id = dex_file.FindTypeId(desc);
+    CHECK(type_id != nullptr) << "Could not find class " << desc;
+    const DexFile::ClassDef* found = dex_file.FindClassDef(dex_file.GetIndexForTypeId(*type_id));
+    CHECK(found != nullptr) << "Could not find class " << desc;
+    return *found;
   }
 
   HiddenApiAccessFlags::ApiList GetFieldHiddenFlags(const char* name,
                                                     uint32_t expected_visibility,
                                                     const DexFile::ClassDef& class_def,
                                                     const DexFile& dex_file) {
-    const uint8_t* class_data = dex_file.GetClassData(class_def);
-    if (class_data == nullptr) {
-      LOG(FATAL) << "Class " << dex_file.GetClassDescriptor(class_def) << " has no data";
-      UNREACHABLE();
-    }
+    ClassAccessor accessor(dex_file, class_def);
+    CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data";
 
-    for (ClassDataItemIterator it(dex_file, class_data); it.HasNext(); it.Next()) {
-      if (it.IsAtMethod()) {
-        break;
-      }
-      const DexFile::FieldId& fid = dex_file.GetFieldId(it.GetMemberIndex());
+    for (const ClassAccessor::Field& field : accessor.GetFields()) {
+      const DexFile::FieldId& fid = dex_file.GetFieldId(field.GetIndex());
       if (strcmp(name, dex_file.GetFieldName(fid)) == 0) {
-        uint32_t actual_visibility = it.GetFieldAccessFlags() & kAccVisibilityFlags;
-        if (actual_visibility != expected_visibility) {
-          LOG(FATAL) << "Field " << name << " in class " << dex_file.GetClassDescriptor(class_def)
-                     << " does not have the expected visibility flags (" << expected_visibility
-                     << " != " << actual_visibility << ")";
-          UNREACHABLE();
-        }
-        return it.DecodeHiddenAccessFlags();
+        const uint32_t actual_visibility = field.GetAccessFlags() & kAccVisibilityFlags;
+        CHECK_EQ(actual_visibility, expected_visibility)
+            << "Field " << name << " in class " << accessor.GetDescriptor();
+        return field.DecodeHiddenAccessFlags();
       }
     }
 
@@ -161,31 +149,18 @@
                                                      bool expected_native,
                                                      const DexFile::ClassDef& class_def,
                                                      const DexFile& dex_file) {
-    const uint8_t* class_data = dex_file.GetClassData(class_def);
-    if (class_data == nullptr) {
-      LOG(FATAL) << "Class " << dex_file.GetClassDescriptor(class_def) << " has no data";
-      UNREACHABLE();
-    }
+    ClassAccessor accessor(dex_file, class_def);
+    CHECK(accessor.HasClassData()) << "Class " << accessor.GetDescriptor() << " has no data";
 
-    for (ClassDataItemIterator it(dex_file, class_data); it.HasNext(); it.Next()) {
-      if (!it.IsAtMethod()) {
-        continue;
-      }
-      const DexFile::MethodId& mid = dex_file.GetMethodId(it.GetMemberIndex());
+    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+      const DexFile::MethodId& mid = dex_file.GetMethodId(method.GetIndex());
       if (strcmp(name, dex_file.GetMethodName(mid)) == 0) {
-        if (expected_native != it.MemberIsNative()) {
-          LOG(FATAL) << "Expected native=" << expected_native << " for method " << name
-                     << " in class " << dex_file.GetClassDescriptor(class_def);
-          UNREACHABLE();
-        }
-        uint32_t actual_visibility = it.GetMethodAccessFlags() & kAccVisibilityFlags;
-        if (actual_visibility != expected_visibility) {
-          LOG(FATAL) << "Method " << name << " in class " << dex_file.GetClassDescriptor(class_def)
-                     << " does not have the expected visibility flags (" << expected_visibility
-                     << " != " << actual_visibility << ")";
-          UNREACHABLE();
-        }
-        return it.DecodeHiddenAccessFlags();
+        CHECK_EQ(expected_native, method.MemberIsNative())
+            << "Method " << name << " in class " << accessor.GetDescriptor();
+        const uint32_t actual_visibility = method.GetAccessFlags() & kAccVisibilityFlags;
+        CHECK_EQ(actual_visibility, expected_visibility)
+            << "Method " << name << " in class " << accessor.GetDescriptor();
+        return method.DecodeHiddenAccessFlags();
       }
     }
 
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index 60aac3c..264217e 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -214,5 +214,15 @@
   description: "java.io.IOException: Error writing ASN.1 encoding",
   result: EXEC_FAILED,
   names: ["libcore.javax.crypto.spec.AlgorithmParametersTestGCM#testEncoding"]
+},
+{
+  description: "Tests fail because mockito can not read android.os.Build$VERSION",
+  result: EXEC_FAILED,
+  bug: 111704422,
+  names: ["libcore.java.lang.ThreadTest#testUncaughtExceptionPreHandler_calledBeforeDefaultHandler",
+          "libcore.java.lang.ThreadTest#testUncaughtExceptionPreHandler_noDefaultHandler",
+          "libcore.javax.crypto.CipherInputStreamTest#testCloseTwice",
+          "libcore.libcore.io.BlockGuardOsTest#test_android_getaddrinfo_networkPolicy",
+          "libcore.libcore.io.BlockGuardOsTest#test_checkNewMethodsInPosix"]
 }
 ]