ObjPtr<>-ify array allocations.

And remove some unnecessary calls to ObjPtr<>::Ptr().

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 31113334
Change-Id: Ie313980f7f23b33b0ccea4fa8d5131d643c59080
diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc
index 75de238..1fe42ad 100644
--- a/compiler/dex/dex_to_dex_decompiler_test.cc
+++ b/compiler/dex/dex_to_dex_decompiler_test.cc
@@ -67,7 +67,7 @@
       class_loader = LoadDex(dex_name);
       updated_dex_file = GetDexFiles(class_loader)[0];
       Runtime::Current()->GetClassLinker()->RegisterDexFile(
-          *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+          *updated_dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
     }
     // The dex files should be identical.
     int cmp = memcmp(original_dex_file->Begin(),
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index 0694c4f..d0a6eb9 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -545,8 +545,7 @@
   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
   for (const DexFile* dex_file : dex_files) {
     ScopedObjectAccess soa(Thread::Current());
-    class_linker->RegisterDexFile(*dex_file,
-                                  soa.Decode<mirror::ClassLoader>(class_loader).Ptr());
+    class_linker->RegisterDexFile(*dex_file, soa.Decode<mirror::ClassLoader>(class_loader));
   }
   compiler_driver_->SetDexFilesForOatFile(dex_files);
   compiler_driver_->CompileAll(class_loader, dex_files, &timings);
diff --git a/openjdkjvm/OpenjdkJvm.cc b/openjdkjvm/OpenjdkJvm.cc
index be1ab78..765225a 100644
--- a/openjdkjvm/OpenjdkJvm.cc
+++ b/openjdkjvm/OpenjdkJvm.cc
@@ -401,7 +401,7 @@
     art::ThrowNullPointerException("object == null");
     return JNI_FALSE;
   }
-  return soa.Self()->HoldsLock(object.Ptr());
+  return soa.Self()->HoldsLock(object);
 }
 
 JNIEXPORT void JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring java_name) {
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 73e3719..50d8dfe 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -526,7 +526,7 @@
     return art::mirror::ByteArray::AllocateAndFill(
         driver_->self_,
         reinterpret_cast<const signed char*>(original_dex_file_.data()),
-        original_dex_file_.size());
+        original_dex_file_.size()).Ptr();
   }
 
   // See if we already have one set.
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 888f713..664b917 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -35,20 +35,19 @@
 namespace art {
 
 inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
-                                                         ObjPtr<mirror::Class>* element_class) {
+                                                         ObjPtr<mirror::Class> element_class) {
   for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
     // Read the cached array class once to avoid races with other threads setting it.
     ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
-    if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
-      return array_class.Ptr();
+    if (array_class != nullptr && array_class->GetComponentType() == element_class) {
+      return array_class;
     }
   }
   std::string descriptor = "[";
   std::string temp;
-  descriptor += (*element_class)->GetDescriptor(&temp);
-  StackHandleScope<2> hs(Thread::Current());
-  Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
-  HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
+  descriptor += element_class->GetDescriptor(&temp);
+  StackHandleScope<1> hs(Thread::Current());
+  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
   ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
   if (array_class != nullptr) {
     // Benign races in storing array class and incrementing index.
@@ -59,7 +58,7 @@
     // We should have a NoClassDefFoundError.
     self->AssertPendingException();
   }
-  return array_class.Ptr();
+  return array_class;
 }
 
 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index dccdff0..6798796 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -432,8 +432,8 @@
   heap->IncrementDisableMovingGC(self);
   StackHandleScope<64> hs(self);  // 64 is picked arbitrarily.
   auto class_class_size = mirror::Class::ClassClassSize(image_pointer_size_);
-  Handle<mirror::Class> java_lang_Class(hs.NewHandle(down_cast<mirror::Class*>(
-      heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor()))));
+  Handle<mirror::Class> java_lang_Class(hs.NewHandle(ObjPtr<mirror::Class>::DownCast(MakeObjPtr(
+      heap->AllocNonMovableObject<true>(self, nullptr, class_class_size, VoidFunctor())))));
   CHECK(java_lang_Class != nullptr);
   java_lang_Class->SetClassFlags(mirror::kClassFlagClass);
   java_lang_Class->SetClass(java_lang_Class.Get());
@@ -988,8 +988,8 @@
   }
 
   class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
-      down_cast<mirror::ObjectArray<mirror::Class>*>(
-          spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)));
+      ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(MakeObjPtr(
+          spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots))));
   DCHECK_EQ(GetClassRoot(ClassRoot::kJavaLangClass, this)->GetClassFlags(),
             mirror::kClassFlagClass);
 
@@ -1094,7 +1094,7 @@
         return false;    // Stop the visit.
       }
       if (name != nullptr) {
-        out_dex_file_names->push_front(name.Ptr());
+        out_dex_file_names->push_front(name);
       }
       return true;  // Continue with the next Element.
     };
@@ -2114,16 +2114,16 @@
   delete data.class_table;
 }
 
-mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length) {
-  return down_cast<mirror::PointerArray*>(
+ObjPtr<mirror::PointerArray> ClassLinker::AllocPointerArray(Thread* self, size_t length) {
+  return ObjPtr<mirror::PointerArray>::DownCast(
       image_pointer_size_ == PointerSize::k64
-          ? static_cast<mirror::Array*>(mirror::LongArray::Alloc(self, length))
-          : static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length)));
+          ? ObjPtr<mirror::Array>(mirror::LongArray::Alloc(self, length))
+          : ObjPtr<mirror::Array>(mirror::IntArray::Alloc(self, length)));
 }
 
-mirror::DexCache* ClassLinker::AllocDexCache(ObjPtr<mirror::String>* out_location,
-                                             Thread* self,
-                                             const DexFile& dex_file) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+                                                    Thread* self,
+                                                    const DexFile& dex_file) {
   StackHandleScope<1> hs(self);
   DCHECK(out_location != nullptr);
   auto dex_cache(hs.NewHandle(ObjPtr<mirror::DexCache>::DownCast(
@@ -2141,9 +2141,9 @@
   return dex_cache.Get();
 }
 
-mirror::DexCache* ClassLinker::AllocAndInitializeDexCache(Thread* self,
-                                                          const DexFile& dex_file,
-                                                          LinearAlloc* linear_alloc) {
+ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self,
+                                                                 const DexFile& dex_file,
+                                                                 LinearAlloc* linear_alloc) {
   ObjPtr<mirror::String> location = nullptr;
   ObjPtr<mirror::DexCache> dex_cache = AllocDexCache(&location, self, dex_file);
   if (dex_cache != nullptr) {
@@ -2156,7 +2156,7 @@
                                          linear_alloc,
                                          image_pointer_size_);
   }
-  return dex_cache.Ptr();
+  return dex_cache;
 }
 
 ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self,
@@ -2179,7 +2179,7 @@
   return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size);
 }
 
-mirror::ObjectArray<mirror::StackTraceElement>* ClassLinker::AllocStackTraceElementArray(
+ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTraceElementArray(
     Thread* self,
     size_t length) {
   return mirror::ObjectArray<mirror::StackTraceElement>::Alloc(
@@ -2260,7 +2260,7 @@
   // Return the loaded class.  No exceptions should be pending.
   CHECK(klass->IsResolved()) << klass->PrettyClass();
   self->AssertNoPendingException();
-  return klass.Ptr();
+  return klass;
 }
 
 typedef std::pair<const DexFile*, const DexFile::ClassDef*> ClassPathEntry;
@@ -2282,7 +2282,7 @@
                                                 const char* descriptor,
                                                 size_t hash,
                                                 Handle<mirror::ClassLoader> class_loader,
-                                                ObjPtr<mirror::Class>* result) {
+                                                /*out*/ ObjPtr<mirror::Class>* result) {
   // Termination case: boot class loader.
   if (IsBootClassLoader(soa, class_loader.Get())) {
     *result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
@@ -2535,7 +2535,7 @@
     if (old == nullptr) {
       old = result_ptr;  // For the comparison below, after releasing the lock.
       if (descriptor_equals) {
-        class_table->InsertWithHash(result_ptr.Ptr(), hash);
+        class_table->InsertWithHash(result_ptr, hash);
         Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader.Get());
       }  // else throw below, after releasing the lock.
     }
@@ -2563,8 +2563,8 @@
         DescriptorToDot(descriptor).c_str());
     return nullptr;
   }
-  // success, return mirror::Class*
-  return result_ptr.Ptr();
+  // Success.
+  return result_ptr;
 }
 
 ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self,
@@ -3612,7 +3612,7 @@
     ObjPtr<mirror::Class> new_class =
         LookupClass(self, descriptor, hash, component_type->GetClassLoader());
     if (new_class != nullptr) {
-      return new_class.Ptr();
+      return new_class;
     }
   }
 
@@ -3713,7 +3713,7 @@
   //
   // (Yes, this happens.)
 
-  return existing.Ptr();
+  return existing;
 }
 
 ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) {
@@ -3763,7 +3763,7 @@
     ClassTable* const class_table = InsertClassTableForClassLoader(class_loader);
     ObjPtr<mirror::Class> existing = class_table->Lookup(descriptor, hash);
     if (existing != nullptr) {
-      return existing.Ptr();
+      return existing;
     }
     VerifyObject(klass);
     class_table->InsertWithHash(klass, hash);
@@ -3817,7 +3817,7 @@
   if (class_table != nullptr) {
     ObjPtr<mirror::Class> result = class_table->Lookup(descriptor, hash);
     if (result != nullptr) {
-      return result.Ptr();
+      return result;
     }
   }
   return nullptr;
@@ -5723,8 +5723,8 @@
         klass->SetVTable(super_vtable);
         return true;
       }
-      vtable = hs.NewHandle(down_cast<mirror::PointerArray*>(
-          super_vtable->CopyOf(self, max_count)));
+      vtable = hs.NewHandle(
+          ObjPtr<mirror::PointerArray>::DownCast(super_vtable->CopyOf(self, max_count)));
       if (UNLIKELY(vtable == nullptr)) {
         self->AssertPendingOOMException();
         return false;
@@ -5860,7 +5860,7 @@
     // Shrink vtable if possible
     CHECK_LE(actual_count, max_count);
     if (actual_count < max_count) {
-      vtable.Assign(down_cast<mirror::PointerArray*>(vtable->CopyOf(self, actual_count)));
+      vtable.Assign(ObjPtr<mirror::PointerArray>::DownCast(vtable->CopyOf(self, actual_count)));
       if (UNLIKELY(vtable == nullptr)) {
         self->AssertPendingOOMException();
         return false;
@@ -5874,7 +5874,7 @@
                             static_cast<int>(num_virtual_methods));
       return false;
     }
-    auto* vtable = AllocPointerArray(self, num_virtual_methods);
+    ObjPtr<mirror::PointerArray> vtable = AllocPointerArray(self, num_virtual_methods);
     if (UNLIKELY(vtable == nullptr)) {
       self->AssertPendingOOMException();
       return false;
@@ -6118,7 +6118,8 @@
         DCHECK(if_table != nullptr);
         DCHECK(if_table->GetMethodArray(i) != nullptr);
         // If we are working on a super interface, try extending the existing method array.
-        method_array = down_cast<mirror::PointerArray*>(if_table->GetMethodArray(i)->Clone(self));
+        method_array = ObjPtr<mirror::PointerArray>::DownCast(MakeObjPtr(
+            if_table->GetMethodArray(i)->Clone(self)));
       } else {
         method_array = AllocPointerArray(self, num_methods);
       }
@@ -6382,7 +6383,7 @@
 // iftable must be large enough to hold all interfaces without changing its size.
 static size_t FillIfTable(ObjPtr<mirror::IfTable> iftable,
                           size_t super_ifcount,
-                          std::vector<mirror::Class*> to_process)
+                          std::vector<ObjPtr<mirror::Class>> to_process)
     REQUIRES(Roles::uninterruptible_)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   // This is the set of all class's already in the iftable. Used to make checking if a class has
@@ -6522,11 +6523,11 @@
   size_t new_ifcount;
   {
     ScopedAssertNoThreadSuspension nts("Copying mirror::Class*'s for FillIfTable");
-    std::vector<mirror::Class*> to_add;
+    std::vector<ObjPtr<mirror::Class>> to_add;
     for (size_t i = 0; i < num_interfaces; i++) {
       ObjPtr<mirror::Class> interface = have_interfaces ? interfaces->Get(i) :
           mirror::Class::GetDirectInterface(self, klass.Get(), i);
-      to_add.push_back(interface.Ptr());
+      to_add.push_back(interface);
     }
 
     new_ifcount = FillIfTable(iftable.Get(), super_ifcount, std::move(to_add));
@@ -6537,7 +6538,7 @@
   // Shrink iftable in case duplicates were found
   if (new_ifcount < ifcount) {
     DCHECK_NE(num_interfaces, 0U);
-    iftable.Assign(down_cast<mirror::IfTable*>(
+    iftable.Assign(ObjPtr<mirror::IfTable>::DownCast(
         iftable->CopyOf(self, new_ifcount * mirror::IfTable::kMax)));
     if (UNLIKELY(iftable == nullptr)) {
       self->AssertPendingOOMException();
@@ -7051,7 +7052,7 @@
                                   default_conflict_methods_.size();
 
   ObjPtr<mirror::PointerArray> vtable =
-      down_cast<mirror::PointerArray*>(old_vtable->CopyOf(self_, new_vtable_count));
+      ObjPtr<mirror::PointerArray>::DownCast(old_vtable->CopyOf(self_, new_vtable_count));
   if (UNLIKELY(vtable == nullptr)) {
     self_->AssertPendingOOMException();
     return nullptr;
@@ -7721,7 +7722,7 @@
     DCHECK(self != nullptr);
     const size_t hash = ComputeModifiedUtf8Hash(descriptor);
     // Find the class in the loaded classes table.
-    type = LookupClass(self, descriptor, hash, class_loader.Ptr());
+    type = LookupClass(self, descriptor, hash, class_loader);
   }
   if (type != nullptr) {
     if (type->IsResolved()) {
@@ -8104,7 +8105,7 @@
 
   ObjPtr<mirror::MethodType> resolved = dex_cache->GetResolvedMethodType(proto_idx);
   if (resolved != nullptr) {
-    return resolved.Ptr();
+    return resolved;
   }
 
   StackHandleScope<4> hs(self);
@@ -8760,7 +8761,7 @@
   DCHECK(dex_file != nullptr);
   Thread* const self = Thread::Current();
   WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
-  ClassTable* const table = ClassTableForClassLoader(class_loader.Ptr());
+  ClassTable* const table = ClassTableForClassLoader(class_loader);
   DCHECK(table != nullptr);
   if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) {
     // It was not already inserted, perform the write barrier to let the GC know the class loader's
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 32016fa..58ce6eb 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -163,7 +163,7 @@
   }
 
   // Finds the array class given for the element class.
-  ObjPtr<mirror::Class> FindArrayClass(Thread* self, ObjPtr<mirror::Class>* element_class)
+  ObjPtr<mirror::Class> FindArrayClass(Thread* self, ObjPtr<mirror::Class> element_class)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
@@ -451,7 +451,7 @@
                                                       LinearAlloc* allocator,
                                                       size_t length);
 
-  mirror::PointerArray* AllocPointerArray(Thread* self, size_t length)
+  ObjPtr<mirror::PointerArray> AllocPointerArray(Thread* self, size_t length)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
@@ -459,8 +459,8 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
-  mirror::ObjectArray<mirror::StackTraceElement>* AllocStackTraceElementArray(Thread* self,
-                                                                              size_t length)
+  ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> AllocStackTraceElementArray(Thread* self,
+                                                                                     size_t length)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
@@ -543,8 +543,9 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  mirror::ObjectArray<mirror::Class>* GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) {
-    mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read<kReadBarrierOption>();
+  ObjPtr<mirror::ObjectArray<mirror::Class>> GetClassRoots() REQUIRES_SHARED(Locks::mutator_lock_) {
+    ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+        class_roots_.Read<kReadBarrierOption>();
     DCHECK(class_roots != nullptr);
     return class_roots;
   }
@@ -777,16 +778,16 @@
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
-  mirror::DexCache* AllocDexCache(ObjPtr<mirror::String>* out_location,
-                                  Thread* self,
-                                  const DexFile& dex_file)
+  ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location,
+                                         Thread* self,
+                                         const DexFile& dex_file)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
   // Used for tests and AppendToBootClassPath.
-  mirror::DexCache* AllocAndInitializeDexCache(Thread* self,
-                                               const DexFile& dex_file,
-                                               LinearAlloc* linear_alloc)
+  ObjPtr<mirror::DexCache> AllocAndInitializeDexCache(Thread* self,
+                                                      const DexFile& dex_file,
+                                                      LinearAlloc* linear_alloc)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_)
       REQUIRES(!Roles::uninterruptible_);
@@ -850,7 +851,7 @@
                                      const char* descriptor,
                                      size_t hash,
                                      Handle<mirror::ClassLoader> class_loader,
-                                     ObjPtr<mirror::Class>* result)
+                                     /*out*/ ObjPtr<mirror::Class>* result)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Locks::dex_lock_);
 
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 5d420aa..e40f1db 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -233,8 +233,7 @@
     ObjPtr<mirror::Class> direct_interface1 =
         mirror::Class::GetDirectInterface(self, array.Get(), 1);
     EXPECT_STREQ(direct_interface1->GetDescriptor(&temp), "Ljava/io/Serializable;");
-    ObjPtr<mirror::Class> array_ptr = array->GetComponentType();
-    EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, &array_ptr), array.Get());
+    EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
 
     PointerSize pointer_size = class_linker_->GetImagePointerSize();
     ObjPtr<mirror::Class> JavaLangObject =
diff --git a/runtime/class_root.h b/runtime/class_root.h
index 5c78198..4aa9801 100644
--- a/runtime/class_root.h
+++ b/runtime/class_root.h
@@ -127,7 +127,7 @@
   ObjPtr<mirror::Class> klass =
       class_roots->GetWithoutChecks<kDefaultVerifyFlags, kReadBarrierOption>(index);
   DCHECK(klass != nullptr);
-  return klass.Ptr();
+  return klass;
 }
 
 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
diff --git a/runtime/debug_print.cc b/runtime/debug_print.cc
index c5bb4d5..cb334b5 100644
--- a/runtime/debug_print.cc
+++ b/runtime/debug_print.cc
@@ -37,7 +37,7 @@
   std::ostringstream oss;
   gc::Heap* heap = Runtime::Current()->GetHeap();
   gc::space::ContinuousSpace* cs =
-      heap->FindContinuousSpaceFromObject(klass.Ptr(), /* fail_ok */ true);
+      heap->FindContinuousSpaceFromObject(klass, /* fail_ok */ true);
   if (cs != nullptr) {
     if (cs->IsImageSpace()) {
       gc::space::ImageSpace* ispace = cs->AsImageSpace();
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 88628bb..f75f47c 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -1388,7 +1388,7 @@
     *new_object_id = 0;
     return JDWP::ERR_OUT_OF_MEMORY;
   }
-  *new_object_id = gRegistry->Add(new_object.Ptr());
+  *new_object_id = gRegistry->Add(new_object);
   return JDWP::ERR_NONE;
 }
 
@@ -1404,10 +1404,9 @@
     return error;
   }
   Thread* self = Thread::Current();
-  gc::Heap* heap = Runtime::Current()->GetHeap();
-  mirror::Array* new_array = mirror::Array::Alloc<true>(self, c, length,
-                                                        c->GetComponentSizeShift(),
-                                                        heap->GetCurrentAllocator());
+  gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+  ObjPtr<mirror::Array> new_array =
+      mirror::Array::Alloc<true>(self, c, length, c->GetComponentSizeShift(), allocator_type);
   if (new_array == nullptr) {
     DCHECK(self->IsExceptionPending());
     self->ClearException();
@@ -1849,7 +1848,7 @@
       return field_value;
 
     case Primitive::kPrimNot:
-      field_value.SetL(f->GetObject(o).Ptr());
+      field_value.SetL(f->GetObject(o));
       return field_value;
 
     case Primitive::kPrimVoid:
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 5cb08dc..9358cbe 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -359,7 +359,7 @@
   ObjPtr<mirror::Class> annotation_member_class =
       soa.Decode<mirror::Class>(WellKnownClasses::libcore_reflect_AnnotationMember);
   ObjPtr<mirror::Class> annotation_member_array_class =
-      class_linker->FindArrayClass(self, &annotation_member_class);
+      class_linker->FindArrayClass(self, annotation_member_class);
   if (annotation_member_array_class == nullptr) {
     return nullptr;
   }
@@ -967,7 +967,7 @@
   ObjPtr<mirror::Class> annotation_array_class =
       soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
   ObjPtr<mirror::Class> annotation_array_array_class =
-      Runtime::Current()->GetClassLinker()->FindArrayClass(self, &annotation_array_class);
+      Runtime::Current()->GetClassLinker()->FindArrayClass(self, annotation_array_class);
   if (annotation_array_array_class == nullptr) {
     return nullptr;
   }
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index f6b1c73..c533f9c 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -268,14 +268,14 @@
 // check.
 template <bool kAccessCheck, bool kInstrumented>
 ALWAYS_INLINE
-inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx,
-                                         int32_t component_count,
-                                         ArtMethod* method,
-                                         Thread* self,
-                                         gc::AllocatorType allocator_type) {
+inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx,
+                                                int32_t component_count,
+                                                ArtMethod* method,
+                                                Thread* self,
+                                                gc::AllocatorType allocator_type) {
   bool slow_path = false;
-  mirror::Class* klass = CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method,
-                                                       &slow_path);
+  ObjPtr<mirror::Class> klass =
+      CheckArrayAlloc<kAccessCheck>(type_idx, component_count, method, &slow_path);
   if (UNLIKELY(slow_path)) {
     if (klass == nullptr) {
       return nullptr;
@@ -306,7 +306,7 @@
   // No need to retry a slow-path allocation as the above code won't cause a GC or thread
   // suspension.
   return mirror::Array::Alloc<kInstrumented>(self, klass, component_count,
-                                             klass->GetComponentSizeShift(), allocator_type);
+                                             klass->GetComponentSizeShift(), allocator_type).Ptr();
 }
 
 template<FindFieldType type, bool access_check>
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index e33de9c..1f4475f 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -87,11 +87,11 @@
 // When verification/compiler hasn't been able to verify access, optionally perform an access
 // check.
 template <bool kAccessCheck, bool kInstrumented>
-ALWAYS_INLINE inline mirror::Array* AllocArrayFromCode(dex::TypeIndex type_idx,
-                                                       int32_t component_count,
-                                                       ArtMethod* method,
-                                                       Thread* self,
-                                                       gc::AllocatorType allocator_type)
+ALWAYS_INLINE inline ObjPtr<mirror::Array> AllocArrayFromCode(dex::TypeIndex type_idx,
+                                                              int32_t component_count,
+                                                              ArtMethod* method,
+                                                              Thread* self,
+                                                              gc::AllocatorType allocator_type)
     REQUIRES_SHARED(Locks::mutator_lock_)
     REQUIRES(!Roles::uninterruptible_);
 
diff --git a/runtime/gc/heap_verification_test.cc b/runtime/gc/heap_verification_test.cc
index 4f06ee6..3869533 100644
--- a/runtime/gc/heap_verification_test.cc
+++ b/runtime/gc/heap_verification_test.cc
@@ -35,7 +35,7 @@
   VerificationTest() {}
 
   template <class T>
-  mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+  ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     return mirror::ObjectArray<T>::Alloc(
         self,
diff --git a/runtime/indirect_reference_table-inl.h b/runtime/indirect_reference_table-inl.h
index 9673bd9..2128f8c 100644
--- a/runtime/indirect_reference_table-inl.h
+++ b/runtime/indirect_reference_table-inl.h
@@ -111,12 +111,12 @@
   if (serial_ == kIRTPrevCount) {
     serial_ = 0;
   }
-  references_[serial_] = GcRoot<mirror::Object>(obj.Ptr());
+  references_[serial_] = GcRoot<mirror::Object>(obj);
 }
 
 inline void IrtEntry::SetReference(ObjPtr<mirror::Object> obj) {
   DCHECK_LT(serial_, kIRTPrevCount);
-  references_[serial_] = GcRoot<mirror::Object>(obj.Ptr());
+  references_[serial_] = GcRoot<mirror::Object>(obj);
 }
 
 }  // namespace art
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index d62f511..e4cc6d3 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -559,7 +559,7 @@
     REQUIRES_SHARED(Locks::mutator_lock_) {
   const Instruction* inst = Instruction::At(dex_pc_ptr);
   int32_t length = shadow_frame->GetVReg(inst->VRegB_22c(inst_data));
-  mirror::Object* obj = AllocArrayFromCode<false, true>(
+  ObjPtr<mirror::Object> obj = AllocArrayFromCode<false, true>(
       dex::TypeIndex(inst->VRegC_22c()), length, shadow_frame->GetMethod(), self,
       Runtime::Current()->GetHeap()->GetCurrentAllocator());
   if (UNLIKELY(obj == nullptr)) {
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 7abb007..667bd03 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1691,7 +1691,7 @@
   ObjPtr<mirror::Class> element_class = reinterpret_cast<mirror::Object*>(args[0])->AsClass();
   Runtime* runtime = Runtime::Current();
   ObjPtr<mirror::Class> array_class =
-      runtime->GetClassLinker()->FindArrayClass(self, &element_class);
+      runtime->GetClassLinker()->FindArrayClass(self, element_class);
   DCHECK(array_class != nullptr);
   gc::AllocatorType allocator = runtime->GetHeap()->GetCurrentAllocator();
   result->SetL(mirror::Array::Alloc<true, true>(self,
@@ -1818,13 +1818,13 @@
   ObjPtr<mirror::Class> element_class = reinterpret_cast<mirror::Class*>(args[0])->AsClass();
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
-  ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, &element_class);
+  ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(self, element_class);
   if (UNLIKELY(array_class == nullptr)) {
     CHECK(self->IsExceptionPending());
     return;
   }
   DCHECK(array_class->IsObjectArrayClass());
-  mirror::Array* new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
+  ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object>::Alloc(
       self, array_class, length, runtime->GetHeap()->GetCurrentAllocator());
   result->SetL(new_array);
 }
diff --git a/runtime/interpreter/unstarted_runtime_test.cc b/runtime/interpreter/unstarted_runtime_test.cc
index 449458c..655713e 100644
--- a/runtime/interpreter/unstarted_runtime_test.cc
+++ b/runtime/interpreter/unstarted_runtime_test.cc
@@ -91,7 +91,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_) {
     Runtime* runtime = Runtime::Current();
     ObjPtr<mirror::Class> array_type =
-        runtime->GetClassLinker()->FindArrayClass(self, &component_type);
+        runtime->GetClassLinker()->FindArrayClass(self, component_type);
     CHECK(array_type != nullptr);
     ObjPtr<mirror::ObjectArray<mirror::Object>> result =
         mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index d8aa00c..b010650 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -471,7 +471,7 @@
     if (kIsDebugBuild) {
       // Ensure the string is strongly interned. b/32995596
       if (object->IsString()) {
-        ObjPtr<mirror::String> str = reinterpret_cast<mirror::String*>(object.Ptr());
+        ObjPtr<mirror::String> str = ObjPtr<mirror::String>::DownCast(object);
         ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
         CHECK(class_linker->GetInternTable()->LookupStrong(Thread::Current(), str) != nullptr);
       }
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index 987c8e9..7290d63 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -2036,14 +2036,14 @@
         return nullptr;
       }
       ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-      array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
+      array_class = class_linker->FindArrayClass(soa.Self(), element_class);
       if (UNLIKELY(array_class == nullptr)) {
         return nullptr;
       }
     }
 
     // Allocate and initialize if necessary.
-    mirror::ObjectArray<mirror::Object>* result =
+    ObjPtr<mirror::ObjectArray<mirror::Object>> result =
         mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), array_class, length);
     if (result != nullptr && initial_element != nullptr) {
       ObjPtr<mirror::Object> initial_object = soa.Decode<mirror::Object>(initial_element);
@@ -2548,7 +2548,7 @@
       soa.Vm()->JniAbortF("NewPrimitiveArray", "negative array length: %d", length);
       return nullptr;
     }
-    ArtT* result = ArtT::Alloc(soa.Self(), length);
+    ObjPtr<ArtT> result = ArtT::Alloc(soa.Self(), length);
     return soa.AddLocalReference<JniT>(result);
   }
 
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 28df174..01a32a2 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -268,7 +268,7 @@
 
     // Then perform the actual boxing, and then set the reference.
     ObjPtr<mirror::Object> boxed = BoxPrimitive(type, src_value);
-    value->SetL(boxed.Ptr());
+    value->SetL(boxed);
     return true;
   } else {
     // The source type is a reference and the target type is a primitive, so we must unbox.
@@ -323,7 +323,7 @@
     // Note: As an optimization, non-moving collectors leave a stale reference value
     // in the references array even after the original vreg was overwritten to a non-reference.
     if (src_value == reinterpret_cast<uintptr_t>(o.Ptr())) {
-      callee_frame->SetVRegReference(dst_reg, o.Ptr());
+      callee_frame->SetVRegReference(dst_reg, o);
     } else {
       callee_frame->SetVReg(dst_reg, src_value);
     }
diff --git a/runtime/method_handles_test.cc b/runtime/method_handles_test.cc
index 0db9551..d123754 100644
--- a/runtime/method_handles_test.cc
+++ b/runtime/method_handles_test.cc
@@ -179,7 +179,7 @@
   StackHandleScope<3> hs(soa.Self());
   static const int32_t kInitialValue = 101;
   JValue value = JValue::FromPrimitive(kInitialValue);
-  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
   Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
   Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
   value.SetL(boxed_value.Get());
@@ -195,8 +195,7 @@
   ClassLinker* cl = Runtime::Current()->GetClassLinker();
   StackHandleScope<3> hs(soa.Self());
   JValue value = JValue::FromPrimitive(3.733e2);
-  Handle<mirror::Object> boxed_value =
-      hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
+  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value));
   Handle<mirror::Class> from = hs.NewHandle(boxed_value->GetClass());
   Handle<mirror::Class> to = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
   value.SetL(boxed_value.Get());
@@ -293,7 +292,7 @@
   StackHandleScope<3> hs(soa.Self());
   const int32_t kInitialValue = 101;
   JValue value = JValue::FromPrimitive(kInitialValue);
-  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
   Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
   Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('I'));
   value.SetL(boxed_value.Get());
@@ -308,7 +307,7 @@
   StackHandleScope<3> hs(soa.Self());
   static const int32_t kInitialValue = 101;
   JValue value = JValue::FromPrimitive(kInitialValue);
-  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
   Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
   Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('J'));
   value.SetL(boxed_value.Get());
@@ -352,7 +351,7 @@
   StackHandleScope<3> hs(soa.Self());
   static const int32_t kInitialValue = 101;
   JValue value = JValue::FromPrimitive(kInitialValue);
-  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value).Ptr());
+  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimInt, value));
   Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Integer;"));
   Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('S'));
   value.SetL(boxed_value.Get());
@@ -368,8 +367,7 @@
   StackHandleScope<3> hs(soa.Self());
   static const double kInitialValue = 1e77;
   JValue value = JValue::FromPrimitive(kInitialValue);
-  Handle<mirror::Object> boxed_value =
-      hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value).Ptr());
+  Handle<mirror::Object> boxed_value = hs.NewHandle(BoxPrimitive(Primitive::kPrimDouble, value));
   Handle<mirror::Class> from = hs.NewHandle(cl->FindSystemClass(soa.Self(), "Ljava/lang/Number;"));
   Handle<mirror::Class> to = hs.NewHandle(cl->FindPrimitiveClass('F'));
   value.SetL(boxed_value.Get());
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index d2adcb4..2e39530 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -151,11 +151,11 @@
 };
 
 template <bool kIsInstrumented, bool kFillUsable>
-inline Array* Array::Alloc(Thread* self,
-                           ObjPtr<Class> array_class,
-                           int32_t component_count,
-                           size_t component_size_shift,
-                           gc::AllocatorType allocator_type) {
+inline ObjPtr<Array> Array::Alloc(Thread* self,
+                                  ObjPtr<Class> array_class,
+                                  int32_t component_count,
+                                  size_t component_size_shift,
+                                  gc::AllocatorType allocator_type) {
   DCHECK(allocator_type != gc::kAllocatorTypeLOS);
   DCHECK(array_class != nullptr);
   DCHECK(array_class->IsArrayClass());
@@ -175,19 +175,19 @@
   }
 #endif
   gc::Heap* heap = Runtime::Current()->GetHeap();
-  Array* result;
+  ObjPtr<Array> result;
   if (!kFillUsable) {
     SetLengthVisitor visitor(component_count);
-    result = down_cast<Array*>(
+    result = ObjPtr<Array>::DownCast(MakeObjPtr(
         heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
-                                                              allocator_type, visitor));
+                                                              allocator_type, visitor)));
   } else {
     SetLengthToUsableSizeVisitor visitor(component_count,
                                          DataOffset(1U << component_size_shift).SizeValue(),
                                          component_size_shift);
-    result = down_cast<Array*>(
+    result = ObjPtr<Array>::DownCast(MakeObjPtr(
         heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
-                                                              allocator_type, visitor));
+                                                              allocator_type, visitor)));
   }
   if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
     array_class = result->GetClass();  // In case the array class moved.
@@ -202,9 +202,9 @@
 }
 
 template<typename T>
-inline PrimitiveArray<T>* PrimitiveArray<T>::AllocateAndFill(Thread* self,
-                                                             const T* data,
-                                                             size_t length) {
+inline ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::AllocateAndFill(Thread* self,
+                                                                   const T* data,
+                                                                   size_t length) {
   StackHandleScope<1> hs(self);
   Handle<PrimitiveArray<T>> arr(hs.NewHandle(PrimitiveArray<T>::Alloc(self, length)));
   if (!arr.IsNull()) {
diff --git a/runtime/mirror/array.cc b/runtime/mirror/array.cc
index 06ce0bb..66ec368 100644
--- a/runtime/mirror/array.cc
+++ b/runtime/mirror/array.cc
@@ -42,17 +42,18 @@
 // piece and work our way in.
 // Recursively create an array with multiple dimensions.  Elements may be
 // Objects or primitive types.
-static Array* RecursiveCreateMultiArray(Thread* self,
-                                        Handle<Class> array_class, int current_dimension,
-                                        Handle<mirror::IntArray> dimensions)
+static ObjPtr<Array> RecursiveCreateMultiArray(Thread* self,
+                                               Handle<Class> array_class,
+                                               int current_dimension,
+                                               Handle<mirror::IntArray> dimensions)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   int32_t array_length = dimensions->Get(current_dimension);
-  StackHandleScope<1> hs(self);
-  Handle<Array> new_array(
-      hs.NewHandle(
-          Array::Alloc<true>(self, array_class.Get(), array_length,
-                             array_class->GetComponentSizeShift(),
-                             Runtime::Current()->GetHeap()->GetCurrentAllocator())));
+  StackHandleScope<2> hs(self);
+  Handle<mirror::Class> h_component_type(hs.NewHandle(array_class->GetComponentType()));
+  size_t component_size_shift = h_component_type->GetPrimitiveTypeSizeShift();
+  gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+  Handle<Array> new_array(hs.NewHandle(Array::Alloc<true>(
+      self, array_class.Get(), array_length, component_size_shift, allocator_type)));
   if (UNLIKELY(new_array == nullptr)) {
     CHECK(self->IsExceptionPending());
     return nullptr;
@@ -60,10 +61,8 @@
   if (current_dimension + 1 < dimensions->GetLength()) {
     // Create a new sub-array in every element of the array.
     for (int32_t i = 0; i < array_length; i++) {
-      StackHandleScope<1> hs2(self);
-      Handle<mirror::Class> h_component_type(hs2.NewHandle(array_class->GetComponentType()));
-      ObjPtr<Array> sub_array = RecursiveCreateMultiArray(self, h_component_type,
-                                                   current_dimension + 1, dimensions);
+      ObjPtr<Array> sub_array =
+          RecursiveCreateMultiArray(self, h_component_type, current_dimension + 1, dimensions);
       if (UNLIKELY(sub_array == nullptr)) {
         CHECK(self->IsExceptionPending());
         return nullptr;
@@ -75,8 +74,9 @@
   return new_array.Get();
 }
 
-Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class,
-                               Handle<IntArray> dimensions) {
+ObjPtr<Array> Array::CreateMultiArray(Thread* self,
+                                      Handle<Class> element_class,
+                                      Handle<IntArray> dimensions) {
   // Verify dimensions.
   //
   // The caller is responsible for verifying that "dimArray" is non-null
@@ -95,17 +95,15 @@
 
   // Find/generate the array class.
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  ObjPtr<mirror::Class>  element_class_ptr = element_class.Get();
   StackHandleScope<1> hs(self);
   MutableHandle<mirror::Class> array_class(
-      hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr)));
+      hs.NewHandle(class_linker->FindArrayClass(self, element_class.Get())));
   if (UNLIKELY(array_class == nullptr)) {
     CHECK(self->IsExceptionPending());
     return nullptr;
   }
   for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
-    ObjPtr<mirror::Class> array_class_ptr = array_class.Get();
-    array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr));
+    array_class.Assign(class_linker->FindArrayClass(self, array_class.Get()));
     if (UNLIKELY(array_class == nullptr)) {
       CHECK(self->IsExceptionPending());
       return nullptr;
@@ -120,13 +118,14 @@
 }
 
 template<typename T>
-PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
-  Array* raw_array = Array::Alloc<true>(self,
-                                        GetClassRoot<PrimitiveArray<T>>(),
-                                        length,
-                                        ComponentSizeShiftWidth(sizeof(T)),
-                                        Runtime::Current()->GetHeap()->GetCurrentAllocator());
-  return down_cast<PrimitiveArray<T>*>(raw_array);
+ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
+  gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
+  ObjPtr<Array> raw_array = Array::Alloc<true>(self,
+                                               GetClassRoot<PrimitiveArray<T>>(),
+                                               length,
+                                               ComponentSizeShiftWidth(sizeof(T)),
+                                               allocator_type);
+  return ObjPtr<PrimitiveArray<T>>::DownCast(raw_array);
 }
 
 void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
@@ -137,7 +136,7 @@
   art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
 }
 
-Array* Array::CopyOf(Thread* self, int32_t new_length) {
+ObjPtr<Array> Array::CopyOf(Thread* self, int32_t new_length) {
   CHECK(GetClass()->GetComponentType()->IsPrimitive()) << "Will miss write barriers";
   DCHECK_GE(new_length, 0);
   // We may get copied by a compacting GC.
@@ -148,7 +147,8 @@
       heap->GetCurrentNonMovingAllocator();
   const auto component_size = GetClass()->GetComponentSize();
   const auto component_shift = GetClass()->GetComponentSizeShift();
-  ObjPtr<Array> new_array = Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
+  ObjPtr<Array> new_array =
+      Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type);
   if (LIKELY(new_array != nullptr)) {
     memcpy(new_array->GetRawData(component_size, 0),
            h_this->GetRawData(component_size, 0),
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index aeaaf673..8bdd561 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -37,17 +37,17 @@
   // least component_count size, however, if there's usable space at the end of the allocation the
   // array will fill it.
   template <bool kIsInstrumented, bool kFillUsable = false>
-  ALWAYS_INLINE static Array* Alloc(Thread* self,
-                                    ObjPtr<Class> array_class,
-                                    int32_t component_count,
-                                    size_t component_size_shift,
-                                    gc::AllocatorType allocator_type)
+  ALWAYS_INLINE static ObjPtr<Array> Alloc(Thread* self,
+                                           ObjPtr<Class> array_class,
+                                           int32_t component_count,
+                                           size_t component_size_shift,
+                                           gc::AllocatorType allocator_type)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
-  static Array* CreateMultiArray(Thread* self,
-                                 Handle<Class> element_class,
-                                 Handle<IntArray> dimensions)
+  static ObjPtr<Array> CreateMultiArray(Thread* self,
+                                        Handle<Class> element_class,
+                                        Handle<IntArray> dimensions)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
@@ -90,7 +90,7 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   ALWAYS_INLINE bool CheckIsValidIndex(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  Array* CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_)
+  ObjPtr<Array> CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
  protected:
@@ -114,10 +114,10 @@
  public:
   typedef T ElementType;
 
-  static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
+  static ObjPtr<PrimitiveArray<T>> Alloc(Thread* self, size_t length)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static PrimitiveArray<T>* AllocateAndFill(Thread* self, const T* data, size_t length)
+  static ObjPtr<PrimitiveArray<T>> AllocateAndFill(Thread* self, const T* data, size_t length)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
 
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index ab50973..8bc7a81 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -294,7 +294,7 @@
   return GetFieldObject<PointerArray>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_));
 }
 
-inline void Class::SetVTable(PointerArray* new_vtable) {
+inline void Class::SetVTable(ObjPtr<PointerArray> new_vtable) {
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable);
 }
 
@@ -487,7 +487,7 @@
     if (UNLIKELY(!this->CanAccess(dex_access_to))) {
       if (throw_on_failure) {
         ThrowIllegalAccessErrorClassForMethodDispatch(this,
-                                                      dex_access_to.Ptr(),
+                                                      dex_access_to,
                                                       method,
                                                       throw_invoke_type);
       }
@@ -800,7 +800,7 @@
       obj = nullptr;
     }
   }
-  return obj.Ptr();
+  return obj;
 }
 
 inline ObjPtr<Object> Class::AllocObject(Thread* self) {
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index a637c86..7adb0d0 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -781,7 +781,7 @@
 
   ALWAYS_INLINE PointerArray* GetVTableDuringLinking() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  void SetVTable(PointerArray* new_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
+  void SetVTable(ObjPtr<PointerArray> new_vtable) REQUIRES_SHARED(Locks::mutator_lock_);
 
   static MemberOffset VTableOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
diff --git a/runtime/mirror/class_ext.cc b/runtime/mirror/class_ext.cc
index 7214620..44bf989 100644
--- a/runtime/mirror/class_ext.cc
+++ b/runtime/mirror/class_ext.cc
@@ -43,8 +43,8 @@
   auto obsolete_dex_cache_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_dex_caches_);
   auto obsolete_methods_off = OFFSET_OF_OBJECT_MEMBER(ClassExt, obsolete_methods_);
   DCHECK(!Runtime::Current()->IsActiveTransaction());
-  SetFieldObject<false>(obsolete_dex_cache_off, dex_caches.Ptr());
-  SetFieldObject<false>(obsolete_methods_off, methods.Ptr());
+  SetFieldObject<false>(obsolete_dex_cache_off, dex_caches);
+  SetFieldObject<false>(obsolete_methods_off, methods);
 }
 
 // We really need to be careful how we update this. If we ever in the future make it so that
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index bfebd5d..2d10b97 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -747,7 +747,7 @@
     } else {
       obj = GetFieldObject<Object>(field_offset);
     }
-    Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true);
+    Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
   }
   if (kVerifyFlags & kVerifyThis) {
     VerifyObject(this);
diff --git a/runtime/mirror/object_array-inl.h b/runtime/mirror/object_array-inl.h
index 086d2f4..ed3c567 100644
--- a/runtime/mirror/object_array-inl.h
+++ b/runtime/mirror/object_array-inl.h
@@ -37,14 +37,15 @@
 namespace mirror {
 
 template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
-                                             ObjPtr<Class> object_array_class,
-                                             int32_t length, gc::AllocatorType allocator_type) {
-  Array* array = Array::Alloc<true>(self,
-                                    object_array_class.Ptr(),
-                                    length,
-                                    ComponentSizeShiftWidth(kHeapReferenceSize),
-                                    allocator_type);
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::Alloc(Thread* self,
+                                                    ObjPtr<Class> object_array_class,
+                                                    int32_t length,
+                                                    gc::AllocatorType allocator_type) {
+  ObjPtr<Array> array = Array::Alloc<true>(self,
+                                           object_array_class,
+                                           length,
+                                           ComponentSizeShiftWidth(kHeapReferenceSize),
+                                           allocator_type);
   if (UNLIKELY(array == nullptr)) {
     return nullptr;
   }
@@ -54,9 +55,9 @@
 }
 
 template<class T>
-inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
-                                             ObjPtr<Class> object_array_class,
-                                             int32_t length) {
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::Alloc(Thread* self,
+                                                    ObjPtr<Class> object_array_class,
+                                                    int32_t length) {
   return Alloc(self,
                object_array_class,
                length,
@@ -346,7 +347,7 @@
 }
 
 template<class T>
-inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
+inline ObjPtr<ObjectArray<T>> ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
   DCHECK_GE(new_length, 0);
   // We may get copied by a compacting GC.
   StackHandleScope<1> hs(self);
@@ -354,7 +355,7 @@
   gc::Heap* heap = Runtime::Current()->GetHeap();
   gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() :
       heap->GetCurrentNonMovingAllocator();
-  ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
+  ObjPtr<ObjectArray<T>> new_array = Alloc(self, GetClass(), new_length, allocator_type);
   if (LIKELY(new_array != nullptr)) {
     new_array->AssignableMemcpy(0, h_this.Get(), 0, std::min(h_this->GetLength(), new_length));
   }
diff --git a/runtime/mirror/object_array.h b/runtime/mirror/object_array.h
index b7a9561..6506f6e 100644
--- a/runtime/mirror/object_array.h
+++ b/runtime/mirror/object_array.h
@@ -31,15 +31,15 @@
     return Array::ClassSize(pointer_size);
   }
 
-  static ObjectArray<T>* Alloc(Thread* self,
-                               ObjPtr<Class> object_array_class,
-                               int32_t length,
-                               gc::AllocatorType allocator_type)
+  static ObjPtr<ObjectArray<T>> Alloc(Thread* self,
+                                      ObjPtr<Class> object_array_class,
+                                      int32_t length,
+                                      gc::AllocatorType allocator_type)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static ObjectArray<T>* Alloc(Thread* self,
-                               ObjPtr<Class> object_array_class,
-                               int32_t length)
+  static ObjPtr<ObjectArray<T>> Alloc(Thread* self,
+                                      ObjPtr<Class> object_array_class,
+                                      int32_t length)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
@@ -99,7 +99,7 @@
                                 bool throw_exception)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
+  ObjPtr<ObjectArray<T>> CopyOf(Thread* self, int32_t new_length)
       REQUIRES_SHARED(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 8b7a1b6..0b615a6 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -76,7 +76,7 @@
   }
 
   template <class T>
-  mirror::ObjectArray<T>* AllocObjectArray(Thread* self, size_t length)
+  ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length)
       REQUIRES_SHARED(Locks::mutator_lock_) {
     return mirror::ObjectArray<T>::Alloc(
         self, GetClassRoot(ClassRoot::kObjectArrayClass, class_linker_), length);
@@ -206,7 +206,8 @@
   ScopedObjectAccess soa(Thread::Current());
   typedef typename ArrayT::ElementType T;
 
-  ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+  StackHandleScope<2> hs(soa.Self());
+  Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
   EXPECT_EQ(2, a->GetLength());
   EXPECT_EQ(0, a->Get(0));
   EXPECT_EQ(0, a->Get(1));
@@ -217,7 +218,6 @@
   EXPECT_EQ(T(123), a->Get(0));
   EXPECT_EQ(T(321), a->Get(1));
 
-  StackHandleScope<1> hs(soa.Self());
   Handle<Class> aioobe = hs.NewHandle(
       cl->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
 
@@ -256,7 +256,8 @@
   ScopedObjectAccess soa(Thread::Current());
   typedef typename ArrayT::ElementType T;
 
-  ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+  StackHandleScope<2> hs(soa.Self());
+  Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
   EXPECT_EQ(2, a->GetLength());
   EXPECT_DOUBLE_EQ(0, a->Get(0));
   EXPECT_DOUBLE_EQ(0, a->Get(1));
@@ -267,7 +268,6 @@
   EXPECT_DOUBLE_EQ(T(123), a->Get(0));
   EXPECT_DOUBLE_EQ(T(321), a->Get(1));
 
-  StackHandleScope<1> hs(soa.Self());
   Handle<Class> aioobe = hs.NewHandle(
       class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
 
@@ -287,7 +287,8 @@
   ScopedObjectAccess soa(Thread::Current());
   typedef typename ArrayT::ElementType T;
 
-  ArrayT* a = ArrayT::Alloc(soa.Self(), 2);
+  StackHandleScope<2> hs(soa.Self());
+  Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2));
   EXPECT_FLOAT_EQ(2, a->GetLength());
   EXPECT_FLOAT_EQ(0, a->Get(0));
   EXPECT_FLOAT_EQ(0, a->Get(1));
@@ -298,7 +299,6 @@
   EXPECT_FLOAT_EQ(T(123), a->Get(0));
   EXPECT_FLOAT_EQ(T(321), a->Get(1));
 
-  StackHandleScope<1> hs(soa.Self());
   Handle<Class> aioobe = hs.NewHandle(
       class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;"));
 
@@ -317,16 +317,17 @@
 TEST_F(ObjectTest, CreateMultiArray) {
   ScopedObjectAccess soa(Thread::Current());
 
-  StackHandleScope<2> hs(soa.Self());
-  Handle<Class> c(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I")));
+  StackHandleScope<4> hs(soa.Self());
+  Handle<Class> int_class(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I")));
+  Handle<Class> int_array_class = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[I"));
   MutableHandle<IntArray> dims(hs.NewHandle(IntArray::Alloc(soa.Self(), 1)));
   dims->Set<false>(0, 1);
-  Array* multi = Array::CreateMultiArray(soa.Self(), c, dims);
-  EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
+  MutableHandle<Array> multi = hs.NewHandle(Array::CreateMultiArray(soa.Self(), int_class, dims));
+  EXPECT_OBJ_PTR_EQ(int_array_class.Get(), multi->GetClass());
   EXPECT_EQ(1, multi->GetLength());
 
   dims->Set<false>(0, -1);
-  multi = Array::CreateMultiArray(soa.Self(), c, dims);
+  multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims));
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
   EXPECT_EQ(mirror::Class::PrettyDescriptor(soa.Self()->GetException()->GetClass()),
             "java.lang.NegativeArraySizeException");
@@ -337,12 +338,12 @@
     for (int j = 0; j < 20; ++j) {
       dims->Set<false>(0, i);
       dims->Set<false>(1, j);
-      multi = Array::CreateMultiArray(soa.Self(), c, dims);
+      multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims));
       EXPECT_TRUE(multi->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[[I"));
       EXPECT_EQ(i, multi->GetLength());
       for (int k = 0; k < i; ++k) {
-        Array* outer = multi->AsObjectArray<Array>()->Get(k);
-        EXPECT_TRUE(outer->GetClass() == class_linker_->FindSystemClass(soa.Self(), "[I"));
+        ObjPtr<Array> outer = multi->AsObjectArray<Array>()->Get(k);
+        EXPECT_OBJ_PTR_EQ(int_array_class.Get(), outer->GetClass());
         EXPECT_EQ(j, outer->GetLength());
       }
     }
@@ -817,7 +818,7 @@
 
   ObjPtr<mirror::Class> c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;");
   ASSERT_TRUE(c != nullptr);
-  mirror::Object* o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
+  ObjPtr<mirror::Object> o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0);
   EXPECT_EQ("java.lang.String[]", mirror::Object::PrettyTypeOf(o));
   EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Object::PrettyTypeOf(o->GetClass()));
 }
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 6c82019..8aed4a8 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -111,7 +111,7 @@
   }
   Runtime* runtime = Runtime::Current();
   ObjPtr<mirror::Class> array_class =
-      runtime->GetClassLinker()->FindArrayClass(soa.Self(), &element_class);
+      runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class);
   if (UNLIKELY(array_class == nullptr)) {
     return nullptr;
   }
@@ -138,7 +138,7 @@
   }
   Runtime* runtime = Runtime::Current();
   ObjPtr<mirror::Class> array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(),
-                                                                                &element_class);
+                                                                                element_class);
   if (UNLIKELY(array_class == nullptr)) {
     return nullptr;
   }
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 38c65f5..5b47eac 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -100,7 +100,7 @@
   }
 
   void AddClass(ObjPtr<mirror::Class> klass) REQUIRES(Locks::mutator_lock_) {
-    class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass.Ptr()));
+    class_set_.insert(self_->GetJniEnv()->AddLocalReference<jclass>(klass));
   }
 
   const std::unordered_set<jclass>& GetClasses() const {
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index c6bdfa1..82e54e2 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -646,8 +646,8 @@
         soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
     ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
         mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(),
-                                                   annotation_array_class.Ptr(),
-                                                   0);
+                                                   annotation_array_class,
+                                                   /* length */ 0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
   }
   return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForClass(klass));
diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc
index a37a76f..13871f7 100644
--- a/runtime/native/java_lang_Thread.cc
+++ b/runtime/native/java_lang_Thread.cc
@@ -119,7 +119,7 @@
     return JNI_FALSE;
   }
   Thread* thread = soa.Self();
-  return thread->HoldsLock(object.Ptr());
+  return thread->HoldsLock(object);
 }
 
 static void Thread_nativeInterrupt(JNIEnv* env, jobject java_thread) {
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 42c7ad5..1ad233a 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -86,7 +86,7 @@
   }
   // If class is erroneous, throw the earlier failure, wrapped in certain cases. See b/28787733.
   if (c != nullptr && c->IsErroneous()) {
-    cl->ThrowEarlierClassFailure(c.Ptr());
+    cl->ThrowEarlierClassFailure(c);
     Thread* self = soa.Self();
     ObjPtr<mirror::Class> iae_class =
         self->DecodeJObject(WellKnownClasses::java_lang_IllegalAccessError)->AsClass();
diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc
index 8bcda10..452a66d 100644
--- a/runtime/native/java_lang_reflect_Array.cc
+++ b/runtime/native/java_lang_reflect_Array.cc
@@ -44,9 +44,8 @@
             Primitive::kPrimInt);
   Handle<mirror::IntArray> dimensions_array(
       hs.NewHandle(ObjPtr<mirror::IntArray>::DownCast(dimensions_obj)));
-  mirror::Array* new_array = mirror::Array::CreateMultiArray(soa.Self(),
-                                                             element_class,
-                                                             dimensions_array);
+  ObjPtr<mirror::Array> new_array =
+      mirror::Array::CreateMultiArray(soa.Self(), element_class, dimensions_array);
   return soa.AddLocalReference<jobject>(new_array);
 }
 
@@ -57,16 +56,16 @@
     ThrowNegativeArraySizeException(length);
     return nullptr;
   }
-  ObjPtr<mirror::Class> element_class = soa.Decode<mirror::Class>(javaElementClass);
   Runtime* runtime = Runtime::Current();
   ClassLinker* class_linker = runtime->GetClassLinker();
-  ObjPtr<mirror::Class> array_class = class_linker->FindArrayClass(soa.Self(), &element_class);
+  ObjPtr<mirror::Class> array_class =
+      class_linker->FindArrayClass(soa.Self(), soa.Decode<mirror::Class>(javaElementClass));
   if (UNLIKELY(array_class == nullptr)) {
     CHECK(soa.Self()->IsExceptionPending());
     return nullptr;
   }
   DCHECK(array_class->IsObjectArrayClass());
-  ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object*>::Alloc(
+  ObjPtr<mirror::Array> new_array = mirror::ObjectArray<mirror::Object>::Alloc(
       soa.Self(),
       array_class,
       length,
diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc
index 2559984..8766692 100644
--- a/runtime/native/java_lang_reflect_Field.cc
+++ b/runtime/native/java_lang_reflect_Field.cc
@@ -476,7 +476,7 @@
     ObjPtr<mirror::Class> annotation_array_class =
         soa.Decode<mirror::Class>(WellKnownClasses::java_lang_annotation_Annotation__array);
     ObjPtr<mirror::ObjectArray<mirror::Object>> empty_array =
-        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class.Ptr(), 0);
+        mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), annotation_array_class, 0);
     return soa.AddLocalReference<jobjectArray>(empty_array);
   }
   return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForField(field));
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 34455fe..87fda6b 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -69,7 +69,7 @@
       // Return an empty array instead of a null pointer
       ObjPtr<mirror::Class> class_array_class = GetClassRoot<mirror::ObjectArray<mirror::Class>>();
       DCHECK(class_array_class != nullptr);
-      mirror::ObjectArray<mirror::Class>* empty_array =
+      ObjPtr<mirror::ObjectArray<mirror::Class>> empty_array =
           mirror::ObjectArray<mirror::Class>::Alloc(soa.Self(), class_array_class, 0);
       return soa.AddLocalReference<jobjectArray>(empty_array);
     } else {
diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc
index 06ea384..0cb5e56 100644
--- a/runtime/reference_table_test.cc
+++ b/runtime/reference_table_test.cc
@@ -106,7 +106,7 @@
   }
 
   // Add a second object 10 times and check dumping is sane.
-  mirror::Object* o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
+  ObjPtr<mirror::Object> o2 = mirror::ShortArray::Alloc(soa.Self(), 0);
   for (size_t i = 0; i < 10; ++i) {
     rt.Add(o2);
     EXPECT_EQ(i + 2, rt.Size());
@@ -276,23 +276,26 @@
   ReferenceTable rt("test", 0, 20);
 
   {
-    mirror::Object* s1 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello");
-    mirror::Object* s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
+    StackHandleScope<1> hs(soa.Self());
+    Handle<mirror::String> s1 =
+        hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"));
+    ObjPtr<mirror::String> s2 = mirror::String::AllocFromModifiedUtf8(soa.Self(), "world");
 
     // 3 copies of s1, 2 copies of s2, interleaved.
     for (size_t i = 0; i != 2; ++i) {
-      rt.Add(s1);
+      rt.Add(s1.Get());
       rt.Add(s2);
     }
-    rt.Add(s1);
+    rt.Add(s1.Get());
   }
 
   {
     // Differently sized byte arrays. Should be sorted by identical (non-unique cound).
-    mirror::Object* b1_1 = mirror::ByteArray::Alloc(soa.Self(), 1);
-    rt.Add(b1_1);
+    StackHandleScope<1> hs(soa.Self());
+    Handle<mirror::ByteArray> b1_1 = hs.NewHandle(mirror::ByteArray::Alloc(soa.Self(), 1));
+    rt.Add(b1_1.Get());
     rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
-    rt.Add(b1_1);
+    rt.Add(b1_1.Get());
     rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
     rt.Add(mirror::ByteArray::Alloc(soa.Self(), 1));
     rt.Add(mirror::ByteArray::Alloc(soa.Self(), 2));
diff --git a/runtime/reflection-inl.h b/runtime/reflection-inl.h
index 26fb021..9fe4bca 100644
--- a/runtime/reflection-inl.h
+++ b/runtime/reflection-inl.h
@@ -121,7 +121,7 @@
   if (UNLIKELY(o == nullptr)) {
     ThrowNullPointerException("null receiver");
     return false;
-  } else if (UNLIKELY(!o->InstanceOf(c.Ptr()))) {
+  } else if (UNLIKELY(!o->InstanceOf(c))) {
     InvalidReceiverError(o, c);
     return false;
   }
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 66eba1e..6aeedd4 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -243,7 +243,7 @@
         // we've seen cases where it's not b/34440020.
         ObjPtr<mirror::Class> dst_class(
             m->ResolveClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_));
-        if (dst_class.Ptr() == nullptr) {
+        if (dst_class == nullptr) {
           CHECK(self->IsExceptionPending());
           return false;
         }
diff --git a/runtime/thread.cc b/runtime/thread.cc
index b59606a..a8133a1 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -491,7 +491,7 @@
 
 Thread* Thread::FromManagedThread(const ScopedObjectAccessAlreadyRunnable& soa,
                                   jobject java_thread) {
-  return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread).Ptr());
+  return FromManagedThread(soa, soa.Decode<mirror::Object>(java_thread));
 }
 
 static size_t FixStackSize(size_t stack_size) {
@@ -2728,7 +2728,7 @@
     depth = std::min(depth, traces_length);
   } else {
     // Create java_trace array and place in local reference table
-    mirror::ObjectArray<mirror::StackTraceElement>* java_traces =
+    ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> java_traces =
         class_linker->AllocStackTraceElementArray(soa.Self(), depth);
     if (java_traces == nullptr) {
       return nullptr;
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 02e61d7..370a619 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -506,7 +506,7 @@
         class_linker_->LookupString(string_idx, h_dex_cache.Get());
     ASSERT_TRUE(s != nullptr);
     EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
-    EXPECT_EQ(s.Ptr(), h_dex_cache->GetResolvedString(string_idx));
+    EXPECT_OBJ_PTR_EQ(s, h_dex_cache->GetResolvedString(string_idx));
   }
   Runtime::Current()->RollbackAndExitTransactionMode();
   // Check that the string did not stay resolved.
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 2e3a659..f57f757 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2932,7 +2932,7 @@
             : called_method->LookupResolvedReturnType();
         if (return_type_class != nullptr) {
           return_type = &FromClass(return_type_descriptor,
-                                   return_type_class.Ptr(),
+                                   return_type_class,
                                    return_type_class->CannotBeAssignedFromOtherTypes());
         } else {
           DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -3685,7 +3685,7 @@
   }
 
   // Record result of class resolution attempt.
-  VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass.Ptr());
+  VerifierDeps::MaybeRecordClassResolution(*dex_file_, class_idx, klass);
 
   // If requested, check if access is allowed. Unresolved types are included in this check, as the
   // interpreter only tests whether access is allowed when a class is not pre-verified and runs in
@@ -4628,9 +4628,7 @@
     std::string temp;
     ObjPtr<mirror::Class> klass = field->GetDeclaringClass();
     const RegType& field_klass =
-        FromClass(klass->GetDescriptor(&temp),
-                  klass.Ptr(),
-                  klass->CannotBeAssignedFromOtherTypes());
+        FromClass(klass->GetDescriptor(&temp), klass, klass->CannotBeAssignedFromOtherTypes());
     if (obj_type.IsUninitializedTypes()) {
       // Field accesses through uninitialized references are only allowable for constructors where
       // the field is declared in this class.
@@ -4731,7 +4729,7 @@
         can_load_classes_ ? field->ResolveType() : field->LookupResolvedType();
     if (field_type_class != nullptr) {
       field_type = &FromClass(field->GetTypeDescriptor(),
-                              field_type_class.Ptr(),
+                              field_type_class,
                               field_type_class->CannotBeAssignedFromOtherTypes());
     } else {
       DCHECK(!can_load_classes_ || self_->IsExceptionPending());
@@ -4919,7 +4917,7 @@
           : method_being_verified_->LookupResolvedReturnType();
       if (return_type_class != nullptr) {
         return_type_ = &FromClass(method_being_verified_->GetReturnTypeDescriptor(),
-                                  return_type_class.Ptr(),
+                                  return_type_class,
                                   return_type_class->CannotBeAssignedFromOtherTypes());
       } else {
         DCHECK(!can_load_classes_ || self_->IsExceptionPending());
diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc
index 73e516c..4a3f9e6 100644
--- a/runtime/verifier/reg_type.cc
+++ b/runtime/verifier/reg_type.cc
@@ -807,7 +807,7 @@
     }
     // Note: The following lookup invalidates existing ObjPtr<>s.
     ObjPtr<mirror::Class> array_class =
-        Runtime::Current()->GetClassLinker()->FindArrayClass(self, &common_elem);
+        Runtime::Current()->GetClassLinker()->FindArrayClass(self, common_elem);
     if (UNLIKELY(array_class == nullptr)) {
       self->AssertPendingException();
       return nullptr;
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 500cc37..fb91976 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -384,7 +384,7 @@
   // Find a boundary making `source` inherit from `destination`. We must find one.
   for (const ObjPtr<mirror::Class>& boundary : boundaries) {
     if (destination->IsAssignableFrom(boundary)) {
-      return boundary.Ptr();
+      return boundary;
     }
   }
   LOG(FATAL) << "Should have found a classpath boundary";
diff --git a/test/497-inlining-and-class-loader/clear_dex_cache.cc b/test/497-inlining-and-class-loader/clear_dex_cache.cc
index c113042..c6fd56f 100644
--- a/test/497-inlining-and-class-loader/clear_dex_cache.cc
+++ b/test/497-inlining-and-class-loader/clear_dex_cache.cc
@@ -52,11 +52,11 @@
     uint32_t index = pair.index;
     ArtMethod* method = pair.object;
     if (sizeof(void*) == 4) {
-      ObjPtr<mirror::IntArray> int_array = down_cast<mirror::IntArray*>(decoded_array.Ptr());
+      ObjPtr<mirror::IntArray> int_array = ObjPtr<mirror::IntArray>::DownCast(decoded_array);
       int_array->Set(2u * i, index);
       int_array->Set(2u * i + 1u, static_cast<jint>(reinterpret_cast<uintptr_t>(method)));
     } else {
-      ObjPtr<mirror::LongArray> long_array = down_cast<mirror::LongArray*>(decoded_array.Ptr());
+      ObjPtr<mirror::LongArray> long_array = ObjPtr<mirror::LongArray>::DownCast(decoded_array);
       long_array->Set(2u * i, index);
       long_array->Set(2u * i + 1u, reinterpret_cast64<jlong>(method));
     }