ObjPtr<>-ify mirror::Object::As*(), fix stale refs in test.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 31113334
Change-Id: Ia04c4996f5cbfa1f26acbadcd747342c57b1aac3
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index e56fdcf..c36f360 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -1140,7 +1140,7 @@
     //
     if (object->IsClass()) {
       bin = Bin::kClassVerified;
-      mirror::Class* klass = object->AsClass();
+      ObjPtr<mirror::Class> klass = object->AsClass();
 
       // Add non-embedded vtable to the pointer array table if there is one.
       ObjPtr<mirror::PointerArray> vtable = klass->GetVTable();
@@ -1810,7 +1810,7 @@
 void ImageWriter::CheckNonImageClassesRemoved() {
   auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
     if (obj->IsClass() && !IsInBootImage(obj)) {
-      Class* klass = obj->AsClass();
+      ObjPtr<Class> klass = obj->AsClass();
       if (!KeepClass(klass)) {
         DumpImageClasses();
         CHECK(KeepClass(klass))
@@ -1978,7 +1978,7 @@
     if (obj->IsString()) {
       // Need to check if the string is already interned in another image info so that we don't have
       // the intern tables of two different images contain the same string.
-      mirror::String* interned = FindInternedString(obj->AsString());
+      mirror::String* interned = FindInternedString(obj->AsString().Ptr());
       if (interned == nullptr) {
         // Not in another image space, insert to our table.
         interned =
@@ -2103,7 +2103,7 @@
     } else if (obj->IsClassLoader()) {
       // Register the class loader if it has a class table.
       // The fake boot class loader should not get registered.
-      mirror::ClassLoader* class_loader = obj->AsClassLoader();
+      ObjPtr<mirror::ClassLoader> class_loader = obj->AsClassLoader();
       if (class_loader->GetClassTable() != nullptr) {
         DCHECK(compiler_options_.IsAppImage());
         if (class_loader == GetAppClassLoader()) {
@@ -2120,7 +2120,7 @@
   }
   if (obj->IsString()) {
     // Always return the interned string if there exists one.
-    mirror::String* interned = FindInternedString(obj->AsString());
+    mirror::String* interned = FindInternedString(obj->AsString().Ptr());
     if (interned != nullptr) {
       return interned;
     }
@@ -3188,7 +3188,7 @@
     }
   }
   if (orig->IsClass()) {
-    FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
+    FixupClass(orig->AsClass<kVerifyNone>().Ptr(), down_cast<mirror::Class*>(copy));
   } else {
     ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
         Runtime::Current()->GetClassLinker()->GetClassRoots();
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 633297e..b14d407 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -2033,12 +2033,15 @@
     if (value == nullptr) {
       os << StringPrintf("null   %s\n", type->PrettyDescriptor().c_str());
     } else if (type->IsStringClass()) {
-      mirror::String* string = value->AsString();
-      os << StringPrintf("%p   String: %s\n", string,
+      ObjPtr<mirror::String> string = value->AsString();
+      os << StringPrintf("%p   String: %s\n",
+                         string.Ptr(),
                          PrintableString(string->ToModifiedUtf8().c_str()).c_str());
     } else if (type->IsClassClass()) {
-      mirror::Class* klass = value->AsClass();
-      os << StringPrintf("%p   Class: %s\n", klass, mirror::Class::PrettyDescriptor(klass).c_str());
+      ObjPtr<mirror::Class> klass = value->AsClass();
+      os << StringPrintf("%p   Class: %s\n",
+                         klass.Ptr(),
+                         mirror::Class::PrettyDescriptor(klass).c_str());
     } else {
       os << StringPrintf("%p   %s\n", value.Ptr(), type->PrettyDescriptor().c_str());
     }
@@ -2156,17 +2159,19 @@
 
     std::ostream& os = vios_.Stream();
 
-    mirror::Class* obj_class = obj->GetClass();
+    ObjPtr<mirror::Class> obj_class = obj->GetClass();
     if (obj_class->IsArrayClass()) {
       os << StringPrintf("%p: %s length:%d\n", obj, obj_class->PrettyDescriptor().c_str(),
                          obj->AsArray()->GetLength());
     } else if (obj->IsClass()) {
-      mirror::Class* klass = obj->AsClass();
-      os << StringPrintf("%p: java.lang.Class \"%s\" (", obj,
+      ObjPtr<mirror::Class> klass = obj->AsClass();
+      os << StringPrintf("%p: java.lang.Class \"%s\" (",
+                         obj,
                          mirror::Class::PrettyDescriptor(klass).c_str())
          << klass->GetStatus() << ")\n";
     } else if (obj_class->IsStringClass()) {
-      os << StringPrintf("%p: java.lang.String %s\n", obj,
+      os << StringPrintf("%p: java.lang.String %s\n",
+                         obj,
                          PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
     } else {
       os << StringPrintf("%p: %s\n", obj, obj_class->PrettyDescriptor().c_str());
@@ -2175,7 +2180,7 @@
     DumpFields(os, obj, obj_class);
     const PointerSize image_pointer_size = image_header_.GetPointerSize();
     if (obj->IsObjectArray()) {
-      auto* obj_array = obj->AsObjectArray<mirror::Object>();
+      ObjPtr<mirror::ObjectArray<mirror::Object>> obj_array = obj->AsObjectArray<mirror::Object>();
       for (int32_t i = 0, length = obj_array->GetLength(); i < length; i++) {
         ObjPtr<mirror::Object> value = obj_array->Get(i);
         size_t run = 0;
diff --git a/openjdkjvmti/ti_class_definition.cc b/openjdkjvmti/ti_class_definition.cc
index c4287fb..ec267155 100644
--- a/openjdkjvmti/ti_class_definition.cc
+++ b/openjdkjvmti/ti_class_definition.cc
@@ -154,8 +154,7 @@
     if (!orig_dex.IsNull()) {
       if (orig_dex->IsArrayInstance()) {
         DCHECK(orig_dex->GetClass()->GetComponentType()->IsPrimitiveByte());
-        art::Handle<art::mirror::ByteArray> orig_dex_bytes(
-            hs.NewHandle(art::down_cast<art::mirror::ByteArray*>(orig_dex->AsArray())));
+        art::Handle<art::mirror::ByteArray> orig_dex_bytes(hs.NewHandle(orig_dex->AsByteArray()));
         dex_data->resize(orig_dex_bytes->GetLength());
         memcpy(dex_data->data(), orig_dex_bytes->GetData(), dex_data->size());
         return;
diff --git a/openjdkjvmti/ti_class_loader.cc b/openjdkjvmti/ti_class_loader.cc
index 348a1ff..999b9d5 100644
--- a/openjdkjvmti/ti_class_loader.cc
+++ b/openjdkjvmti/ti_class_loader.cc
@@ -92,8 +92,6 @@
   art::ArtField* cookie_field = java_dex_file->GetClass()->FindDeclaredInstanceField(
       "mCookie", "Ljava/lang/Object;");
   CHECK(internal_cookie_field != nullptr);
-  art::ObjPtr<art::mirror::LongArray> orig_internal_cookie(
-      internal_cookie_field->GetObject(java_dex_file)->AsLongArray());
   art::ObjPtr<art::mirror::LongArray> orig_cookie(
       cookie_field->GetObject(java_dex_file)->AsLongArray());
   internal_cookie_field->SetObject<false>(java_dex_file, new_cookie);
diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc
index 7f71954..3d99ed8 100644
--- a/openjdkjvmti/ti_heap.cc
+++ b/openjdkjvmti/ti_heap.cc
@@ -1073,7 +1073,7 @@
       REQUIRES_SHARED(art::Locks::mutator_lock_)
       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
     if (obj->IsClass()) {
-      VisitClass(obj->AsClass());
+      VisitClass(obj->AsClass().Ptr());
       return;
     }
     if (obj->IsArrayInstance()) {
@@ -1138,7 +1138,7 @@
     }
 
     if (array->IsObjectArray()) {
-      art::mirror::ObjectArray<art::mirror::Object>* obj_array =
+      art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> obj_array =
           array->AsObjectArray<art::mirror::Object>();
       int32_t length = obj_array->GetLength();
       for (int32_t i = 0; i != length; ++i) {
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 27ac88f..0ed27fc 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -468,7 +468,7 @@
   return OK;
 }
 
-art::mirror::Class* Redefiner::ClassRedefinition::GetMirrorClass() {
+art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::GetMirrorClass() {
   return driver_->self_->DecodeJObject(klass_)->AsClass();
 }
 
@@ -1239,7 +1239,7 @@
 }
 
 void Redefiner::ClassRedefinition::UnregisterJvmtiBreakpoints() {
-  BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass());
+  BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass().Ptr());
 }
 
 void Redefiner::ClassRedefinition::UnregisterBreakpoints() {
diff --git a/openjdkjvmti/ti_redefine.h b/openjdkjvmti/ti_redefine.h
index ac3f7d3..f55a2b8 100644
--- a/openjdkjvmti/ti_redefine.h
+++ b/openjdkjvmti/ti_redefine.h
@@ -115,7 +115,7 @@
       other.driver_ = nullptr;
     }
 
-    art::mirror::Class* GetMirrorClass() REQUIRES_SHARED(art::Locks::mutator_lock_);
+    art::ObjPtr<art::mirror::Class> GetMirrorClass() REQUIRES_SHARED(art::Locks::mutator_lock_);
     art::ObjPtr<art::mirror::ClassLoader> GetClassLoader()
         REQUIRES_SHARED(art::Locks::mutator_lock_);
 
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index c810b41..6832821 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -31,8 +31,10 @@
 AotClassLinker::~AotClassLinker() {}
 
 // Wrap the original InitializeClass with creation of transaction when in strict mode.
-bool AotClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
-                                  bool can_init_statics, bool can_init_parents) {
+bool AotClassLinker::InitializeClass(Thread* self,
+                                     Handle<mirror::Class> klass,
+                                     bool can_init_statics,
+                                     bool can_init_parents) {
   Runtime* const runtime = Runtime::Current();
   bool strict_mode_ = runtime->IsActiveStrictTransactionMode();
 
@@ -52,7 +54,7 @@
   }
 
   if (strict_mode_) {
-    runtime->EnterTransactionMode(true, klass.Get()->AsClass());
+    runtime->EnterTransactionMode(true, klass.Get()->AsClass().Ptr());
   }
   bool success = ClassLinker::InitializeClass(self, klass, can_init_statics, can_init_parents);
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b74e81f..6e12eba 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1757,10 +1757,10 @@
   const ImageHeader& header = space->GetImageHeader();
   ObjPtr<mirror::Object> dex_caches_object = header.GetImageRoot(ImageHeader::kDexCaches);
   DCHECK(dex_caches_object != nullptr);
-  mirror::ObjectArray<mirror::DexCache>* dex_caches =
+  ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
       dex_caches_object->AsObjectArray<mirror::DexCache>();
   const OatFile* oat_file = space->GetOatFile();
-  for (int32_t i = 0; i < dex_caches->GetLength(); i++) {
+  for (int32_t i = 0, length = dex_caches->GetLength(); i != length; ++i) {
     ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get(i);
     std::string dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8());
     std::unique_ptr<const DexFile> dex_file = OpenOatDexFile(oat_file,
diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc
index e890c1f..66d134e 100644
--- a/runtime/class_loader_context.cc
+++ b/runtime/class_loader_context.cc
@@ -865,7 +865,7 @@
     return true;
   }
   // On the Java side, the dex files are stored in the cookie field.
-  mirror::LongArray* long_array = cookie_field->GetObject(java_dex_file)->AsLongArray();
+  ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(java_dex_file)->AsLongArray();
   if (long_array == nullptr) {
     // This should never happen so log a warning.
     LOG(ERROR) << "Unexpected null cookie";
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 3518efd..f2402cc 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -413,9 +413,9 @@
   return thread->IsSuspended() && thread->GetDebugSuspendCount() > 0;
 }
 
-static mirror::Array* DecodeNonNullArray(JDWP::RefTypeId id, JDWP::JdwpError* error)
+static ObjPtr<mirror::Array> DecodeNonNullArray(JDWP::RefTypeId id, JDWP::JdwpError* error)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
+  ObjPtr<mirror::Object> o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
   if (o == nullptr) {
     *error = JDWP::ERR_INVALID_OBJECT;
     return nullptr;
@@ -428,9 +428,9 @@
   return o->AsArray();
 }
 
-static mirror::Class* DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError* error)
+static ObjPtr<mirror::Class> DecodeClass(JDWP::RefTypeId id, JDWP::JdwpError* error)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  mirror::Object* o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
+  ObjPtr<mirror::Object> o = Dbg::GetObjectRegistry()->Get<mirror::Object*>(id, error);
   if (o == nullptr) {
     *error = JDWP::ERR_INVALID_OBJECT;
     return nullptr;
@@ -447,7 +447,8 @@
                             JDWP::JdwpError* error)
     REQUIRES_SHARED(Locks::mutator_lock_)
     REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_) {
-  mirror::Object* thread_peer = Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_id, error);
+  ObjPtr<mirror::Object> thread_peer =
+      Dbg::GetObjectRegistry()->Get<mirror::Object*>(thread_id, error);
   if (thread_peer == nullptr) {
     // This isn't even an object.
     *error = JDWP::ERR_INVALID_OBJECT;
@@ -765,7 +766,7 @@
 
 std::string Dbg::GetClassName(JDWP::RefTypeId class_id) {
   JDWP::JdwpError error;
-  mirror::Object* o = gRegistry->Get<mirror::Object*>(class_id, &error);
+  ObjPtr<mirror::Object> o = gRegistry->Get<mirror::Object*>(class_id, &error);
   if (o == nullptr) {
     if (error == JDWP::ERR_NONE) {
       return "null";
@@ -774,12 +775,12 @@
     }
   }
   if (!o->IsClass()) {
-    return StringPrintf("non-class %p", o);  // This is only used for debugging output anyway.
+    return StringPrintf("non-class %p", o.Ptr());  // This is only used for debugging output anyway.
   }
   return GetClassName(o->AsClass());
 }
 
-std::string Dbg::GetClassName(mirror::Class* klass) {
+std::string Dbg::GetClassName(ObjPtr<mirror::Class> klass) {
   if (klass == nullptr) {
     return "null";
   }
@@ -789,7 +790,7 @@
 
 JDWP::JdwpError Dbg::GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id) {
   JDWP::JdwpError status;
-  mirror::Class* c = DecodeClass(id, &status);
+  ObjPtr<mirror::Class> c = DecodeClass(id, &status);
   if (c == nullptr) {
     *class_object_id = 0;
     return status;
@@ -800,7 +801,7 @@
 
 JDWP::JdwpError Dbg::GetSuperclass(JDWP::RefTypeId id, JDWP::RefTypeId* superclass_id) {
   JDWP::JdwpError status;
-  mirror::Class* c = DecodeClass(id, &status);
+  ObjPtr<mirror::Class> c = DecodeClass(id, &status);
   if (c == nullptr) {
     *superclass_id = 0;
     return status;
@@ -816,7 +817,7 @@
 
 JDWP::JdwpError Dbg::GetClassLoader(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -826,7 +827,7 @@
 
 JDWP::JdwpError Dbg::GetModifiers(JDWP::RefTypeId id, JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -847,7 +848,7 @@
 
 JDWP::JdwpError Dbg::GetMonitorInfo(JDWP::ObjectId object_id, JDWP::ExpandBuf* reply) {
   JDWP::JdwpError error;
-  mirror::Object* o = gRegistry->Get<mirror::Object*>(object_id, &error);
+  ObjPtr<mirror::Object> o = gRegistry->Get<mirror::Object*>(object_id, &error);
   if (o == nullptr) {
     return JDWP::ERR_INVALID_OBJECT;
   }
@@ -860,7 +861,7 @@
   {
     ScopedThreadSuspension sts(self, kSuspended);
     ScopedSuspendAll ssa(__FUNCTION__);
-    monitor_info = MonitorInfo(o);
+    monitor_info = MonitorInfo(o.Ptr());
   }
   if (monitor_info.owner_ != nullptr) {
     expandBufAddObjectId(reply, gRegistry->Add(monitor_info.owner_->GetPeerFromOtherThread()));
@@ -1062,7 +1063,7 @@
 
 JDWP::JdwpError Dbg::GetReflectedType(JDWP::RefTypeId class_id, JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1099,7 +1100,7 @@
 JDWP::JdwpError Dbg::GetClassInfo(JDWP::RefTypeId class_id, JDWP::JdwpTypeTag* pTypeTag,
                                   uint32_t* pStatus, std::string* pDescriptor) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1150,7 +1151,7 @@
 
 JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signature) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1162,7 +1163,7 @@
 JDWP::JdwpError Dbg::GetSourceDebugExtension(JDWP::RefTypeId class_id,
                                              std::string* extension_data) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1178,7 +1179,7 @@
 
 JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1234,7 +1235,7 @@
 
 JDWP::JdwpError Dbg::GetArrayLength(JDWP::ObjectId array_id, int32_t* length) {
   JDWP::JdwpError error;
-  mirror::Array* a = DecodeNonNullArray(array_id, &error);
+  ObjPtr<mirror::Array> a = DecodeNonNullArray(array_id, &error);
   if (a == nullptr) {
     return error;
   }
@@ -1242,9 +1243,12 @@
   return JDWP::ERR_NONE;
 }
 
-JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id, int offset, int count, JDWP::ExpandBuf* pReply) {
+JDWP::JdwpError Dbg::OutputArray(JDWP::ObjectId array_id,
+                                 int offset,
+                                 int count,
+                                 JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError error;
-  mirror::Array* a = DecodeNonNullArray(array_id, &error);
+  ObjPtr<mirror::Array> a = DecodeNonNullArray(array_id, &error);
   if (a == nullptr) {
     return error;
   }
@@ -1275,7 +1279,7 @@
     }
   } else {
     ScopedObjectAccessUnchecked soa(Thread::Current());
-    mirror::ObjectArray<mirror::Object>* oa = a->AsObjectArray<mirror::Object>();
+    ObjPtr<mirror::ObjectArray<mirror::Object>> oa = a->AsObjectArray<mirror::Object>();
     for (int i = 0; i < count; ++i) {
       ObjPtr<mirror::Object> element = oa->Get(offset + i);
       JDWP::JdwpTag specific_tag = (element != nullptr) ? TagFromObject(soa, element)
@@ -1289,7 +1293,7 @@
 }
 
 template <typename T>
-static void CopyArrayData(mirror::Array* a, JDWP::Request* src, int offset, int count)
+static void CopyArrayData(ObjPtr<mirror::Array> a, JDWP::Request* src, int offset, int count)
     NO_THREAD_SAFETY_ANALYSIS {
   // TODO: fix when annotalysis correctly handles non-member functions.
   DCHECK(a->GetClass()->IsPrimitiveArray());
@@ -1303,7 +1307,7 @@
 JDWP::JdwpError Dbg::SetArrayElements(JDWP::ObjectId array_id, int offset, int count,
                                       JDWP::Request* request) {
   JDWP::JdwpError error;
-  mirror::Array* dst = DecodeNonNullArray(array_id, &error);
+  ObjPtr<mirror::Array> dst = DecodeNonNullArray(array_id, &error);
   if (dst == nullptr) {
     return error;
   }
@@ -1326,10 +1330,10 @@
       CopyArrayData<uint8_t>(dst, request, offset, count);
     }
   } else {
-    mirror::ObjectArray<mirror::Object>* oa = dst->AsObjectArray<mirror::Object>();
+    ObjPtr<mirror::ObjectArray<mirror::Object>> oa = dst->AsObjectArray<mirror::Object>();
     for (int i = 0; i < count; ++i) {
       JDWP::ObjectId id = request->ReadObjectId();
-      mirror::Object* o = gRegistry->Get<mirror::Object*>(id, &error);
+      ObjPtr<mirror::Object> o = gRegistry->Get<mirror::Object*>(id, &error);
       if (error != JDWP::ERR_NONE) {
         return error;
       }
@@ -1360,7 +1364,7 @@
 
 JDWP::JdwpError Dbg::CreateObject(JDWP::RefTypeId class_id, JDWP::ObjectId* new_object_id) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     *new_object_id = 0;
     return error;
@@ -1391,7 +1395,7 @@
 JDWP::JdwpError Dbg::CreateArrayObject(JDWP::RefTypeId array_class_id, uint32_t length,
                                        JDWP::ObjectId* new_array_id) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(array_class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(array_class_id, &error);
   if (c == nullptr) {
     *new_array_id = 0;
     return error;
@@ -1591,7 +1595,7 @@
 JDWP::JdwpError Dbg::OutputDeclaredFields(JDWP::RefTypeId class_id, bool with_generic,
                                           JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1619,7 +1623,7 @@
 JDWP::JdwpError Dbg::OutputDeclaredMethods(JDWP::RefTypeId class_id, bool with_generic,
                                            JDWP::ExpandBuf* pReply) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(class_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
   if (c == nullptr) {
     return error;
   }
@@ -1827,7 +1831,7 @@
                                          bool is_static)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   JDWP::JdwpError error;
-  mirror::Class* c = DecodeClass(ref_type_id, &error);
+  ObjPtr<mirror::Class> c = DecodeClass(ref_type_id, &error);
   if (ref_type_id != 0 && c == nullptr) {
     return error;
   }
@@ -1841,7 +1845,7 @@
   }
   ArtField* f = FromFieldId(field_id);
 
-  mirror::Class* receiver_class = c;
+  ObjPtr<mirror::Class> receiver_class = c;
   if (receiver_class == nullptr && o != nullptr) {
     receiver_class = o->GetClass();
   }
@@ -3888,7 +3892,7 @@
                    << "it is fully resumed.";
     }
 
-    mirror::Object* receiver = gRegistry->Get<mirror::Object*>(object_id, &error);
+    ObjPtr<mirror::Object> receiver = gRegistry->Get<mirror::Object*>(object_id, &error);
     if (error != JDWP::ERR_NONE) {
       return JDWP::ERR_INVALID_OBJECT;
     }
@@ -3898,7 +3902,7 @@
       return JDWP::ERR_INVALID_OBJECT;
     }
 
-    mirror::Class* c = DecodeClass(class_id, &error);
+    ObjPtr<mirror::Class> c = DecodeClass(class_id, &error);
     if (c == nullptr) {
       return error;
     }
@@ -3926,8 +3930,8 @@
 
     {
       StackHandleScope<2> hs(soa.Self());
-      HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver));
-      HandleWrapper<mirror::Class> h_klass(hs.NewHandleWrapper(&c));
+      HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&receiver));
+      HandleWrapperObjPtr<mirror::Class> h_klass(hs.NewHandleWrapper(&c));
       const dex::TypeList* types = m->GetParameterTypeList();
       for (size_t i = 0; i < arg_count; ++i) {
         if (shorty[i + 1] != JdwpTagToShortyChar(arg_types[i])) {
@@ -3954,8 +3958,8 @@
     }
 
     // Allocates a DebugInvokeReq.
-    DebugInvokeReq* req = new (std::nothrow) DebugInvokeReq(request_id, thread_id, receiver, c, m,
-                                                            options, arg_values, arg_count);
+    DebugInvokeReq* req = new (std::nothrow) DebugInvokeReq(
+        request_id, thread_id, receiver, c, m, options, arg_values, arg_count);
     if (req == nullptr) {
       LOG(ERROR) << "Failed to allocate DebugInvokeReq";
       return JDWP::ERR_OUT_OF_MEMORY;
@@ -4723,12 +4727,12 @@
       LOG(ERROR) << "Invalid object in managed heap: " << o;
       return HPSG_STATE(SOLIDITY_HARD, KIND_NATIVE);
     }
-    mirror::Class* c = o->GetClass();
+    ObjPtr<mirror::Class> c = o->GetClass();
     if (c == nullptr) {
       // The object was probably just created but hasn't been initialized yet.
       return HPSG_STATE(SOLIDITY_HARD, KIND_OBJECT);
     }
-    if (!heap->IsValidObjectAddress(c)) {
+    if (!heap->IsValidObjectAddress(c.Ptr())) {
       LOG(ERROR) << "Invalid class for managed heap object: " << o << " " << c;
       return HPSG_STATE(SOLIDITY_HARD, KIND_UNKNOWN);
     }
diff --git a/runtime/debugger.h b/runtime/debugger.h
index 1dbf8be..de44b14 100644
--- a/runtime/debugger.h
+++ b/runtime/debugger.h
@@ -74,13 +74,23 @@
  * Invoke-during-breakpoint support.
  */
 struct DebugInvokeReq {
-  DebugInvokeReq(uint32_t invoke_request_id, JDWP::ObjectId invoke_thread_id,
-                 mirror::Object* invoke_receiver, mirror::Class* invoke_class,
-                 ArtMethod* invoke_method, uint32_t invoke_options,
-                 uint64_t args[], uint32_t args_count)
-      : request_id(invoke_request_id), thread_id(invoke_thread_id), receiver(invoke_receiver),
-        klass(invoke_class), method(invoke_method), arg_count(args_count), arg_values(args),
-        options(invoke_options), reply(JDWP::expandBufAlloc()) {
+  DebugInvokeReq(uint32_t invoke_request_id,
+                 JDWP::ObjectId invoke_thread_id,
+                 ObjPtr<mirror::Object> invoke_receiver,
+                 ObjPtr<mirror::Class> invoke_class,
+                 ArtMethod* invoke_method,
+                 uint32_t invoke_options,
+                 uint64_t args[],
+                 uint32_t args_count)
+      : request_id(invoke_request_id),
+        thread_id(invoke_thread_id),
+        receiver(invoke_receiver),
+        klass(invoke_class),
+        method(invoke_method),
+        arg_count(args_count),
+        arg_values(args),
+        options(invoke_options),
+        reply(JDWP::expandBufAlloc()) {
   }
 
   ~DebugInvokeReq() {
@@ -285,7 +295,7 @@
    */
   static std::string GetClassName(JDWP::RefTypeId id)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  static std::string GetClassName(mirror::Class* klass)
+  static std::string GetClassName(ObjPtr<mirror::Class> klass)
       REQUIRES_SHARED(Locks::mutator_lock_);
   static JDWP::JdwpError GetClassObject(JDWP::RefTypeId id, JDWP::ObjectId* class_object_id)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -319,7 +329,9 @@
 
   static JDWP::JdwpError GetArrayLength(JDWP::ObjectId array_id, int32_t* length)
       REQUIRES_SHARED(Locks::mutator_lock_);
-  static JDWP::JdwpError OutputArray(JDWP::ObjectId array_id, int offset, int count,
+  static JDWP::JdwpError OutputArray(JDWP::ObjectId array_id,
+                                     int offset,
+                                     int count,
                                      JDWP::ExpandBuf* pReply)
       REQUIRES_SHARED(Locks::mutator_lock_);
   static JDWP::JdwpError SetArrayElements(JDWP::ObjectId array_id, int offset, int count,
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 11365cb..ee2ab56 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -164,7 +164,7 @@
     ThrowNullPointerException("null array in FILL_ARRAY_DATA");
     return false;
   }
-  mirror::Array* array = obj->AsArray();
+  ObjPtr<mirror::Array> array = obj->AsArray();
   DCHECK(!array->IsObjectArray());
   if (UNLIKELY(static_cast<int32_t>(payload->element_count) > array->GetLength())) {
     Thread* self = Thread::Current();
diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc
index cd10e12..854defe 100644
--- a/runtime/gc/collector/concurrent_copying.cc
+++ b/runtime/gc/collector/concurrent_copying.cc
@@ -3237,7 +3237,7 @@
     dummy_obj->SetClass(int_array_class);
     CHECK(dummy_obj->IsArrayInstance<kVerifyNone>());
     int32_t length = (byte_size - data_offset) / component_size;
-    mirror::Array* dummy_arr = dummy_obj->AsArray<kVerifyNone>();
+    ObjPtr<mirror::Array> dummy_arr = dummy_obj->AsArray<kVerifyNone>();
     dummy_arr->SetLength(length);
     CHECK_EQ(dummy_arr->GetLength(), length)
         << "byte_size=" << byte_size << " length=" << length
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 1a611df..7a565bd 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -3226,7 +3226,7 @@
 
           // Print which field of the object is dead.
           if (!obj->IsObjectArray()) {
-            mirror::Class* klass = is_static ? obj->AsClass() : obj->GetClass();
+            ObjPtr<mirror::Class> klass = is_static ? obj->AsClass() : obj->GetClass();
             CHECK(klass != nullptr);
             for (ArtField& field : (is_static ? klass->GetSFields() : klass->GetIFields())) {
               if (field.GetOffset().Int32Value() == offset.Int32Value()) {
@@ -3236,7 +3236,7 @@
               }
             }
           } else {
-            mirror::ObjectArray<mirror::Object>* object_array =
+            ObjPtr<mirror::ObjectArray<mirror::Object>> object_array =
                 obj->AsObjectArray<mirror::Object>();
             for (int32_t i = 0; i < object_array->GetLength(); ++i) {
               if (object_array->Get(i) == ref) {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 4550dd7..2177676 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -489,13 +489,15 @@
   }
 
   // Visitor for VisitReferences().
-  ALWAYS_INLINE void operator()(mirror::Object* object, MemberOffset field_offset, bool is_static)
+  ALWAYS_INLINE void operator()(ObjPtr<mirror::Object> object,
+                                MemberOffset field_offset,
+                                bool is_static)
       const REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK(!is_static);
     PatchReferenceField(object, field_offset);
   }
   // Visitor for VisitReferences(), java.lang.ref.Reference case.
-  ALWAYS_INLINE void operator()(ObjPtr<mirror::Class> klass, mirror::Reference* ref) const
+  ALWAYS_INLINE void operator()(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Reference> ref) const
       REQUIRES_SHARED(Locks::mutator_lock_) {
     DCHECK(klass->IsTypeOfReferenceClass());
     this->operator()(ref, mirror::Reference::ReferentOffset(), /*is_static=*/ false);
@@ -1260,8 +1262,9 @@
       image_header.RelocateImageObjects(app_image_objects.Delta());
       CHECK_EQ(image_header.GetImageBegin(), target_base);
       // Fix up dex cache DexFile pointers.
-      auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)->
-          AsObjectArray<mirror::DexCache, kVerifyNone>();
+      ObjPtr<mirror::ObjectArray<mirror::DexCache>> dex_caches =
+          image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)
+              ->AsObjectArray<mirror::DexCache, kVerifyNone>();
       for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) {
         ObjPtr<mirror::DexCache> dex_cache = dex_caches->Get<kVerifyNone, kWithoutReadBarrier>(i);
         CHECK(dex_cache != nullptr);
@@ -1674,10 +1677,11 @@
         if (!patched_objects->Test(object)) {
           // This is the last pass over objects, so we do not need to Set().
           patch_object_visitor.VisitObject(object);
-          mirror::Class* klass = object->GetClass<kVerifyNone, kWithoutReadBarrier>();
+          ObjPtr<mirror::Class> klass = object->GetClass<kVerifyNone, kWithoutReadBarrier>();
           if (klass->IsDexCacheClass<kVerifyNone>()) {
             // Patch dex cache array pointers and elements.
-            mirror::DexCache* dex_cache = object->AsDexCache<kVerifyNone, kWithoutReadBarrier>();
+            ObjPtr<mirror::DexCache> dex_cache =
+                object->AsDexCache<kVerifyNone, kWithoutReadBarrier>();
             patch_object_visitor.VisitDexCacheArrays(dex_cache);
           } else if (klass == method_class || klass == constructor_class) {
             // Patch the ArtMethod* in the mirror::Executable subobject.
diff --git a/runtime/gc/space/space_test.h b/runtime/gc/space/space_test.h
index 7fbd0b5..01d0d68 100644
--- a/runtime/gc/space/space_test.h
+++ b/runtime/gc/space/space_test.h
@@ -53,7 +53,7 @@
     heap->SetSpaceAsDefault(space);
   }
 
-  mirror::Class* GetByteArrayClass(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
+  ObjPtr<mirror::Class> GetByteArrayClass(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
     if (byte_array_class_ == nullptr) {
       ObjPtr<mirror::Class> byte_array_class =
           Runtime::Current()->GetClassLinker()->FindSystemClass(self, "[B");
@@ -112,7 +112,7 @@
       // the correct read barrier state.
       o->AssertReadBarrierState();
     }
-    mirror::Array* arr = o->AsArray<kVerifyNone>();
+    ObjPtr<mirror::Array> arr = o->AsArray<kVerifyNone>();
     size_t header_size = SizeOfZeroLengthByteArray();
     int32_t length = size - header_size;
     arr->SetLength(length);
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index b89ece3..8440c41 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -1172,9 +1172,9 @@
     // allocated which hasn't been initialized yet.
   } else {
     if (obj->IsClass()) {
-      DumpHeapClass(obj->AsClass());
+      DumpHeapClass(obj->AsClass().Ptr());
     } else if (c->IsArrayClass()) {
-      DumpHeapArray(obj->AsArray(), c);
+      DumpHeapArray(obj->AsArray().Ptr(), c);
     } else {
       DumpHeapInstanceObject(obj, c, visitor.GetRoots());
     }
@@ -1439,7 +1439,7 @@
     __ AddClassId(LookupClassId(klass));
 
     // Dump the elements, which are always objects or null.
-    __ AddIdList(obj->AsObjectArray<mirror::Object>());
+    __ AddIdList(obj->AsObjectArray<mirror::Object>().Ptr());
   } else {
     size_t size;
     HprofBasicType t = SignatureToBasicTypeAndSize(
@@ -1525,11 +1525,11 @@
     }
     // Add value field for String if necessary.
     if (klass->IsStringClass()) {
-      mirror::String* s = obj->AsString();
+      ObjPtr<mirror::String> s = obj->AsString();
       if (s->GetLength() == 0) {
         // If string is empty, use an object-aligned address within the string for the value.
         string_value = reinterpret_cast<mirror::Object*>(
-            reinterpret_cast<uintptr_t>(s) + kObjectAlignment);
+            reinterpret_cast<uintptr_t>(s.Ptr()) + kObjectAlignment);
       } else {
         if (s->IsCompressed()) {
           string_value = reinterpret_cast<mirror::Object*>(s->GetValueCompressed());
@@ -1553,7 +1553,7 @@
   // Output native value character array for strings.
   CHECK_EQ(obj->IsString(), string_value != nullptr);
   if (string_value != nullptr) {
-    mirror::String* s = obj->AsString();
+    ObjPtr<mirror::String> s = obj->AsString();
     __ AddU1(HPROF_PRIMITIVE_ARRAY_DUMP);
     __ AddObjectId(string_value);
     __ AddStackTraceSerialNumber(LookupStackTraceSerialNumber(obj));
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index a106305..30c4b90 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -1833,12 +1833,12 @@
 
 // TODO: Use ObjPtr here.
 template<typename T>
-static void RecordArrayElementsInTransactionImpl(mirror::PrimitiveArray<T>* array,
+static void RecordArrayElementsInTransactionImpl(ObjPtr<mirror::PrimitiveArray<T>> array,
                                                  int32_t count)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   Runtime* runtime = Runtime::Current();
   for (int32_t i = 0; i < count; ++i) {
-    runtime->RecordWriteArray(array, i, array->GetWithoutChecks(i));
+    runtime->RecordWriteArray(array.Ptr(), i, array->GetWithoutChecks(i));
   }
 }
 
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 8b8567e..6d4d209 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -172,7 +172,9 @@
   }
 }
 
-static mirror::String* GetClassName(Thread* self, ShadowFrame* shadow_frame, size_t arg_offset)
+static ObjPtr<mirror::String> GetClassName(Thread* self,
+                                           ShadowFrame* shadow_frame,
+                                           size_t arg_offset)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   mirror::Object* param = shadow_frame->GetVRegReference(arg_offset);
   if (param == nullptr) {
@@ -205,15 +207,16 @@
                                                    size_t arg_offset,
                                                    bool long_form,
                                                    const char* caller) {
-  mirror::String* class_name = GetClassName(self, shadow_frame, arg_offset);
+  ObjPtr<mirror::String> class_name = GetClassName(self, shadow_frame, arg_offset);
   if (class_name == nullptr) {
     return;
   }
   bool initialize_class;
-  mirror::ClassLoader* class_loader;
+  ObjPtr<mirror::ClassLoader> class_loader;
   if (long_form) {
     initialize_class = shadow_frame->GetVReg(arg_offset + 1) != 0;
-    class_loader = down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset + 2));
+    class_loader =
+        ObjPtr<mirror::ClassLoader>::DownCast(shadow_frame->GetVRegReference(arg_offset + 2));
   } else {
     initialize_class = true;
     // TODO: This is really only correct for the boot classpath, and for robustness we should
@@ -428,7 +431,7 @@
     ThrowNullPointerExceptionForMethodAccess(shadow_frame->GetMethod(), InvokeType::kVirtual);
     return;
   }
-  mirror::ObjectArray<mirror::Class>* args =
+  ObjPtr<mirror::ObjectArray<mirror::Class>> args =
       shadow_frame->GetVRegReference(arg_offset + 1)->AsObjectArray<mirror::Class>();
   Runtime* runtime = Runtime::Current();
   bool transaction = runtime->IsActiveTransaction();
@@ -561,7 +564,7 @@
     return;
   }
   CHECK(resource_obj->IsString());
-  mirror::String* resource_name = resource_obj->AsString();
+  ObjPtr<mirror::String> resource_name = resource_obj->AsString();
 
   std::string resource_name_str = resource_name->ToModifiedUtf8();
   if (resource_name_str.empty() || resource_name_str == "/") {
@@ -746,9 +749,9 @@
 
 void UnstartedRuntime::UnstartedVmClassLoaderFindLoadedClass(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
-  mirror::ClassLoader* class_loader =
-      down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset));
+  ObjPtr<mirror::String> class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
+  ObjPtr<mirror::ClassLoader> class_loader =
+      ObjPtr<mirror::ClassLoader>::DownCast(shadow_frame->GetVRegReference(arg_offset));
   StackHandleScope<2> hs(self);
   Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
   Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
@@ -769,8 +772,10 @@
 
 template <typename T>
 static void PrimitiveArrayCopy(Thread* self,
-                               mirror::Array* src_array, int32_t src_pos,
-                               mirror::Array* dst_array, int32_t dst_pos,
+                               ObjPtr<mirror::Array> src_array,
+                               int32_t src_pos,
+                               ObjPtr<mirror::Array> dst_array,
+                               int32_t dst_pos,
                                int32_t length)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (src_array->GetClass()->GetComponentType() != dst_array->GetClass()->GetComponentType()) {
@@ -782,8 +787,8 @@
                                dst_array->GetClass()->GetComponentType()).c_str());
     return;
   }
-  mirror::PrimitiveArray<T>* src = down_cast<mirror::PrimitiveArray<T>*>(src_array);
-  mirror::PrimitiveArray<T>* dst = down_cast<mirror::PrimitiveArray<T>*>(dst_array);
+  ObjPtr<mirror::PrimitiveArray<T>> src = ObjPtr<mirror::PrimitiveArray<T>>::DownCast(src_array);
+  ObjPtr<mirror::PrimitiveArray<T>> dst = ObjPtr<mirror::PrimitiveArray<T>>::DownCast(dst_array);
   const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= length);
   if (copy_forward) {
     for (int32_t i = 0; i < length; ++i) {
@@ -820,8 +825,8 @@
     return;
   }
 
-  mirror::Array* src_array = src_obj->AsArray();
-  mirror::Array* dst_array = dst_obj->AsArray();
+  ObjPtr<mirror::Array> src_array = src_obj->AsArray();
+  ObjPtr<mirror::Array> dst_array = dst_obj->AsArray();
 
   // Bounds checking. Throw IndexOutOfBoundsException.
   if (UNLIKELY(src_pos < 0) || UNLIKELY(dst_pos < 0) || UNLIKELY(length < 0) ||
@@ -851,8 +856,8 @@
       return;
     }
 
-    mirror::ObjectArray<mirror::Object>* src = src_array->AsObjectArray<mirror::Object>();
-    mirror::ObjectArray<mirror::Object>* dst = dst_array->AsObjectArray<mirror::Object>();
+    ObjPtr<mirror::ObjectArray<mirror::Object>> src = src_array->AsObjectArray<mirror::Object>();
+    ObjPtr<mirror::ObjectArray<mirror::Object>> dst = dst_array->AsObjectArray<mirror::Object>();
     if (src == dst) {
       // Can overlap, but not have type mismatches.
       // We cannot use ObjectArray::MemMove here, as it doesn't support transactions.
@@ -1246,7 +1251,7 @@
     Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Null pointer in peekArray");
     return;
   }
-  mirror::Array* array = obj->AsArray();
+  ObjPtr<mirror::Array> array = obj->AsArray();
 
   int offset = shadow_frame->GetVReg(arg_offset + 3);
   int count = shadow_frame->GetVReg(arg_offset + 4);
@@ -1260,7 +1265,7 @@
   switch (type) {
     case Primitive::kPrimByte: {
       int8_t* address = reinterpret_cast<int8_t*>(static_cast<intptr_t>(address_long));
-      mirror::ByteArray* byte_array = array->AsByteArray();
+      ObjPtr<mirror::ByteArray> byte_array = array->AsByteArray();
       for (int32_t i = 0; i < count; ++i, ++address) {
         byte_array->SetWithoutChecks<true>(i + offset, *address);
       }
@@ -1297,7 +1302,7 @@
   jint start = shadow_frame->GetVReg(arg_offset + 1);
   jint end = shadow_frame->GetVReg(arg_offset + 2);
   jint index = shadow_frame->GetVReg(arg_offset + 4);
-  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  ObjPtr<mirror::String> string = shadow_frame->GetVRegReference(arg_offset)->AsString();
   if (string == nullptr) {
     AbortTransactionOrFail(self, "String.getCharsNoCheck with null object");
     return;
@@ -1318,7 +1323,7 @@
 void UnstartedRuntime::UnstartedStringCharAt(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
   jint index = shadow_frame->GetVReg(arg_offset + 1);
-  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  ObjPtr<mirror::String> string = shadow_frame->GetVRegReference(arg_offset)->AsString();
   if (string == nullptr) {
     AbortTransactionOrFail(self, "String.charAt with null object");
     return;
@@ -1359,7 +1364,7 @@
 // This allows creating the new style of String objects during compilation.
 void UnstartedRuntime::UnstartedStringFactoryNewStringFromString(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
-  mirror::String* to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  ObjPtr<mirror::String> to_copy = shadow_frame->GetVRegReference(arg_offset)->AsString();
   if (to_copy == nullptr) {
     AbortTransactionOrFail(self, "StringFactory.newStringFromString with null object");
     return;
@@ -1392,7 +1397,7 @@
 void UnstartedRuntime::UnstartedStringToCharArray(
     Thread* self, ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  mirror::String* string = shadow_frame->GetVRegReference(arg_offset)->AsString();
+  ObjPtr<mirror::String> string = shadow_frame->GetVRegReference(arg_offset)->AsString();
   if (string == nullptr) {
     AbortTransactionOrFail(self, "String.charAt with null object");
     return;
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index c032650..370f19b 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -1973,7 +1973,7 @@
       soa.Vm()->JniAbortF("GetArrayLength", "not an array: %s", obj->PrettyTypeOf().c_str());
       return 0;
     }
-    mirror::Array* array = obj->AsArray();
+    ObjPtr<mirror::Array> array = obj->AsArray();
     return array->GetLength();
   }
 
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 3a0cbe2..19d35a8 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -22,7 +22,6 @@
 #include <android-base/logging.h>
 
 #include "base/bit_utils.h"
-#include "base/casts.h"
 #include "class.h"
 #include "obj_ptr-inl.h"
 #include "runtime.h"
@@ -253,11 +252,11 @@
 template<bool kTransactionActive, bool kUnchecked>
 inline void PointerArray::SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) {
   if (ptr_size == PointerSize::k64) {
-    (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this)) : AsLongArray())->
+    (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this)) : AsLongArray())->
         SetWithoutChecks<kTransactionActive>(idx, element);
   } else {
     DCHECK_LE(element, static_cast<uint64_t>(0xFFFFFFFFu));
-    (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this)) : AsIntArray())
+    (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this)) : AsIntArray())
         ->SetWithoutChecks<kTransactionActive>(idx, static_cast<uint32_t>(element));
   }
 }
@@ -291,16 +290,16 @@
   DCHECK(!Runtime::Current()->IsActiveTransaction());
   DCHECK(!src.IsNull());
   if (ptr_size == PointerSize::k64) {
-    LongArray* l_this = (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(this))
-                                    : AsLongArray());
-    LongArray* l_src = (kUnchecked ? down_cast<LongArray*>(static_cast<Object*>(src.Ptr()))
-                                   : src->AsLongArray());
+    ObjPtr<LongArray> l_this = (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(this))
+                                           : AsLongArray());
+    ObjPtr<LongArray> l_src = (kUnchecked ? ObjPtr<LongArray>::DownCast(ObjPtr<Object>(src))
+                                          : src->AsLongArray());
     l_this->Memcpy(dst_pos, l_src, src_pos, count);
   } else {
-    IntArray* i_this = (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(this))
-                                   : AsIntArray());
-    IntArray* i_src = (kUnchecked ? down_cast<IntArray*>(static_cast<Object*>(src.Ptr()))
-                                  : src->AsIntArray());
+    ObjPtr<IntArray> i_this = (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(this))
+                                          : AsIntArray());
+    ObjPtr<IntArray> i_src = (kUnchecked ? ObjPtr<IntArray>::DownCast(ObjPtr<Object>(src.Ptr()))
+                                         : src->AsIntArray());
     i_this->Memcpy(dst_pos, i_src, src_pos, count);
   }
 }
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 3fa5d80..e203658 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -148,9 +148,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline Class* Object::AsClass() {
+inline ObjPtr<Class> Object::AsClass() {
   DCHECK((IsClass<kVerifyFlags>()));
-  return down_cast<Class*>(this);
+  return ObjPtr<Class>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -164,9 +164,9 @@
 }
 
 template<class T, VerifyObjectFlags kVerifyFlags>
-inline ObjectArray<T>* Object::AsObjectArray() {
+inline ObjPtr<ObjectArray<T>> Object::AsObjectArray() {
   DCHECK((IsObjectArray<kVerifyFlags>()));
-  return down_cast<ObjectArray<T>*>(this);
+  return ObjPtr<ObjectArray<T>>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -182,15 +182,15 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
-inline Reference* Object::AsReference() {
+inline ObjPtr<Reference> Object::AsReference() {
   DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>()));
-  return down_cast<Reference*>(this);
+  return ObjPtr<Reference>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline Array* Object::AsArray() {
+inline ObjPtr<Array> Object::AsArray() {
   DCHECK((IsArrayInstance<kVerifyFlags>()));
-  return down_cast<Array*>(this);
+  return ObjPtr<Array>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags, Primitive::Type kType>
@@ -210,9 +210,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline BooleanArray* Object::AsBooleanArray() {
+inline ObjPtr<BooleanArray> Object::AsBooleanArray() {
   DCHECK(IsBooleanArray<kVerifyFlags>());
-  return down_cast<BooleanArray*>(this);
+  return ObjPtr<BooleanArray>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -221,9 +221,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline ByteArray* Object::AsByteArray() {
+inline ObjPtr<ByteArray> Object::AsByteArray() {
   DCHECK(IsByteArray<kVerifyFlags>());
-  return down_cast<ByteArray*>(this);
+  return ObjPtr<ByteArray>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -232,9 +232,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline CharArray* Object::AsCharArray() {
+inline ObjPtr<CharArray> Object::AsCharArray() {
   DCHECK(IsCharArray<kVerifyFlags>());
-  return down_cast<CharArray*>(this);
+  return ObjPtr<CharArray>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -243,9 +243,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline ShortArray* Object::AsShortArray() {
+inline ObjPtr<ShortArray> Object::AsShortArray() {
   DCHECK(IsShortArray<kVerifyFlags>());
-  return down_cast<ShortArray*>(this);
+  return ObjPtr<ShortArray>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -254,11 +254,11 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline IntArray* Object::AsIntArrayUnchecked() {
-  return down_cast<IntArray*>(this);
+inline ObjPtr<IntArray> Object::AsIntArrayUnchecked() {
+  return ObjPtr<IntArray>::DownCast(this);
 }
 template<VerifyObjectFlags kVerifyFlags>
-inline IntArray* Object::AsIntArray() {
+inline ObjPtr<IntArray> Object::AsIntArray() {
   DCHECK((IsIntArray<kVerifyFlags>()));
   return AsIntArrayUnchecked<kVerifyFlags>();
 }
@@ -269,11 +269,11 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline LongArray* Object::AsLongArrayUnchecked() {
-  return down_cast<LongArray*>(this);
+inline ObjPtr<LongArray> Object::AsLongArrayUnchecked() {
+  return ObjPtr<LongArray>::DownCast(this);
 }
 template<VerifyObjectFlags kVerifyFlags>
-inline LongArray* Object::AsLongArray() {
+inline ObjPtr<LongArray> Object::AsLongArray() {
   DCHECK((IsLongArray<kVerifyFlags>()));
   return AsLongArrayUnchecked<kVerifyFlags>();
 }
@@ -284,9 +284,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline FloatArray* Object::AsFloatArray() {
+inline ObjPtr<FloatArray> Object::AsFloatArray() {
   DCHECK(IsFloatArray<kVerifyFlags>());
-  return down_cast<FloatArray*>(this);
+  return ObjPtr<FloatArray>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -295,9 +295,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline DoubleArray* Object::AsDoubleArray() {
+inline ObjPtr<DoubleArray> Object::AsDoubleArray() {
   DCHECK(IsDoubleArray<kVerifyFlags>());
-  return down_cast<DoubleArray*>(this);
+  return ObjPtr<DoubleArray>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
@@ -306,15 +306,15 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
-inline String* Object::AsString() {
+inline ObjPtr<String> Object::AsString() {
   DCHECK((IsString<kVerifyFlags, kReadBarrierOption>()));
-  return down_cast<String*>(this);
+  return ObjPtr<String>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline Throwable* Object::AsThrowable() {
+inline ObjPtr<Throwable> Object::AsThrowable() {
   DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
-  return down_cast<Throwable*>(this);
+  return ObjPtr<Throwable>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -333,9 +333,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags>
-inline FinalizerReference* Object::AsFinalizerReference() {
+inline ObjPtr<FinalizerReference> Object::AsFinalizerReference() {
   DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
-  return down_cast<FinalizerReference*>(this);
+  return ObjPtr<FinalizerReference>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags>
@@ -918,9 +918,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
-inline mirror::ClassLoader* Object::AsClassLoader() {
+inline ObjPtr<ClassLoader> Object::AsClassLoader() {
   DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>()));
-  return down_cast<mirror::ClassLoader*>(this);
+  return ObjPtr<ClassLoader>::DownCast(this);
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
@@ -929,9 +929,9 @@
 }
 
 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
-inline mirror::DexCache* Object::AsDexCache() {
+inline ObjPtr<mirror::DexCache> Object::AsDexCache() {
   DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>()));
-  return down_cast<mirror::DexCache*>(this);
+  return ObjPtr<DexCache>::DownCast(this);
 }
 
 template<bool kTransactionActive, bool kCheckTransaction>
diff --git a/runtime/mirror/object-refvisitor-inl.h b/runtime/mirror/object-refvisitor-inl.h
index f0bee5a..f98c433 100644
--- a/runtime/mirror/object-refvisitor-inl.h
+++ b/runtime/mirror/object-refvisitor-inl.h
@@ -58,12 +58,13 @@
         VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
         ref_visitor(klass, AsReference<kVerifyFlags, kReadBarrierOption>());
       } else if (class_flags == kClassFlagDexCache) {
-        mirror::DexCache* const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
+        ObjPtr<mirror::DexCache> const dex_cache = AsDexCache<kVerifyFlags, kReadBarrierOption>();
         dex_cache->VisitReferences<kVisitNativeRoots,
                                    kVerifyFlags,
                                    kReadBarrierOption>(klass, visitor);
       } else {
-        mirror::ClassLoader* const class_loader = AsClassLoader<kVerifyFlags, kReadBarrierOption>();
+        ObjPtr<mirror::ClassLoader> const class_loader =
+            AsClassLoader<kVerifyFlags, kReadBarrierOption>();
         class_loader->VisitReferences<kVisitNativeRoots,
                                       kVerifyFlags,
                                       kReadBarrierOption>(klass, visitor);
diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc
index b8d1d3f..739e0b1 100644
--- a/runtime/mirror/object.cc
+++ b/runtime/mirror/object.cc
@@ -57,7 +57,7 @@
     dest_obj_->SetFieldObjectWithoutWriteBarrier<false, false>(offset, ref);
   }
 
-  void operator()(ObjPtr<mirror::Class> klass, mirror::Reference* ref) const
+  void operator()(ObjPtr<mirror::Class> klass, ObjPtr<mirror::Reference> ref) const
       ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) {
     // Copy java.lang.ref.Reference.referent which isn't visited in
     // Object::VisitReferences().
@@ -125,7 +125,7 @@
   ObjPtr<Class> c = src->GetClass();
   if (c->IsArrayClass()) {
     if (!c->GetComponentType()->IsPrimitive()) {
-      ObjectArray<Object>* array = dest->AsObjectArray<Object>();
+      ObjPtr<ObjectArray<Object>> array = dest->AsObjectArray<Object>();
       WriteBarrier::ForArrayWrite(dest, 0, array->GetLength());
     }
   } else {
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index f727085..2d69206 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -172,75 +172,75 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsClass() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  Class* AsClass() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<Class> AsClass() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsObjectArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<class T, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ObjectArray<T>* AsObjectArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<ObjectArray<T>> AsObjectArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   bool IsClassLoader() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  ClassLoader* AsClassLoader() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<ClassLoader> AsClassLoader() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   bool IsDexCache() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  DexCache* AsDexCache() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<DexCache> AsDexCache() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsArrayInstance() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  Array* AsArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<Array> AsArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsBooleanArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  BooleanArray* AsBooleanArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<BooleanArray> AsBooleanArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsByteArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ByteArray* AsByteArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<ByteArray> AsByteArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsCharArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  CharArray* AsCharArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<CharArray> AsCharArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsShortArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  ShortArray* AsShortArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<ShortArray> AsShortArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsIntArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  IntArray* AsIntArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<IntArray> AsIntArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  IntArray* AsIntArrayUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<IntArray> AsIntArrayUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsLongArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  LongArray* AsLongArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<LongArray> AsLongArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  LongArray* AsLongArrayUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<LongArray> AsLongArrayUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsFloatArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  FloatArray* AsFloatArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<FloatArray> AsFloatArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsDoubleArray() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  DoubleArray* AsDoubleArray() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<DoubleArray> AsDoubleArray() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
@@ -248,17 +248,17 @@
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  String* AsString() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<String> AsString() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  Throwable* AsThrowable() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<Throwable> AsThrowable() REQUIRES_SHARED(Locks::mutator_lock_);
 
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
   bool IsReferenceInstance() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
            ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
-  Reference* AsReference() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<Reference> AsReference() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsWeakReferenceInstance() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
@@ -266,7 +266,7 @@
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsFinalizerReferenceInstance() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  FinalizerReference* AsFinalizerReference() REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<FinalizerReference> AsFinalizerReference() REQUIRES_SHARED(Locks::mutator_lock_);
   template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
   bool IsPhantomReferenceInstance() REQUIRES_SHARED(Locks::mutator_lock_);
 
diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc
index e4bc8ce..63cbd2c 100644
--- a/runtime/native/java_lang_System.cc
+++ b/runtime/native/java_lang_System.cc
@@ -127,9 +127,9 @@
             dstPos, ObjPtr<mirror::LongArray>::DownCast(srcArray), srcPos, count);
         return;
       case Primitive::kPrimNot: {
-        mirror::ObjectArray<mirror::Object>* dstObjArray =
+        ObjPtr<mirror::ObjectArray<mirror::Object>> dstObjArray =
             dstArray->AsObjectArray<mirror::Object>();
-        mirror::ObjectArray<mirror::Object>* srcObjArray =
+        ObjPtr<mirror::ObjectArray<mirror::Object>> srcObjArray =
             srcArray->AsObjectArray<mirror::Object>();
         dstObjArray->AssignableMemmove(dstPos, srcObjArray, srcPos, count);
         return;
diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc
index df06a9f..a4f3df2 100644
--- a/runtime/runtime_callbacks_test.cc
+++ b/runtime/runtime_callbacks_test.cc
@@ -448,14 +448,14 @@
         return false;
       }
       std::lock_guard<std::mutex> lock(ref_guard_);
-      mirror::Class* k = obj->AsClass();
+      ObjPtr<mirror::Class> k = obj->AsClass();
       ClassReference test = { &k->GetDexFile(), k->GetDexClassDefIndex() };
       return ref_ == test;
     }
 
     void SetInterestingObject(mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
       std::lock_guard<std::mutex> lock(ref_guard_);
-      mirror::Class* k = obj->AsClass();
+      ObjPtr<mirror::Class> k = obj->AsClass();
       ref_ = { &k->GetDexFile(), k->GetDexClassDefIndex() };
     }
 
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 47c4604..f4222ae 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1347,7 +1347,7 @@
   DumpStack(os, dump_native_stack, backtrace_map, force_dump_stack);
 }
 
-mirror::String* Thread::GetThreadName() const {
+ObjPtr<mirror::String> Thread::GetThreadName() const {
   ArtField* f = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_name);
   if (tlsPtr_.opeer == nullptr) {
     return nullptr;
diff --git a/runtime/thread.h b/runtime/thread.h
index 085bd98..7c8ad24 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -395,7 +395,7 @@
   }
 
   // Returns the java.lang.Thread's name, or null if this Thread* doesn't have a peer.
-  mirror::String* GetThreadName() const REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<mirror::String> GetThreadName() const REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Sets 'name' to the java.lang.Thread's name. This requires no transition to managed code,
   // allocation, or locking.
diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc
index 69ded3d..fb0a5d9 100644
--- a/runtime/transaction_test.cc
+++ b/runtime/transaction_test.cc
@@ -357,7 +357,7 @@
 // Tests static array fields are reset to their default value after transaction rollback.
 TEST_F(TransactionTest, StaticArrayFieldsTest) {
   ScopedObjectAccess soa(Thread::Current());
-  StackHandleScope<4> hs(soa.Self());
+  StackHandleScope<13> hs(soa.Self());
   Handle<mirror::ClassLoader> class_loader(
       hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
   ASSERT_TRUE(class_loader != nullptr);
@@ -373,65 +373,73 @@
   // Lookup fields.
   ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
   ASSERT_TRUE(booleanArrayField != nullptr);
-  mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray();
+  Handle<mirror::BooleanArray> booleanArray = hs.NewHandle(
+      booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray());
   ASSERT_TRUE(booleanArray != nullptr);
   ASSERT_EQ(booleanArray->GetLength(), 1);
   ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
 
   ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
   ASSERT_TRUE(byteArrayField != nullptr);
-  mirror::ByteArray* byteArray = byteArrayField->GetObject(h_klass.Get())->AsByteArray();
+  Handle<mirror::ByteArray> byteArray =
+      hs.NewHandle(byteArrayField->GetObject(h_klass.Get())->AsByteArray());
   ASSERT_TRUE(byteArray != nullptr);
   ASSERT_EQ(byteArray->GetLength(), 1);
   ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
 
   ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
   ASSERT_TRUE(charArrayField != nullptr);
-  mirror::CharArray* charArray = charArrayField->GetObject(h_klass.Get())->AsCharArray();
+  Handle<mirror::CharArray> charArray =
+      hs.NewHandle(charArrayField->GetObject(h_klass.Get())->AsCharArray());
   ASSERT_TRUE(charArray != nullptr);
   ASSERT_EQ(charArray->GetLength(), 1);
   ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
 
   ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
   ASSERT_TRUE(shortArrayField != nullptr);
-  mirror::ShortArray* shortArray = shortArrayField->GetObject(h_klass.Get())->AsShortArray();
+  Handle<mirror::ShortArray> shortArray =
+      hs.NewHandle(shortArrayField->GetObject(h_klass.Get())->AsShortArray());
   ASSERT_TRUE(shortArray != nullptr);
   ASSERT_EQ(shortArray->GetLength(), 1);
   ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
 
   ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
   ASSERT_TRUE(intArrayField != nullptr);
-  mirror::IntArray* intArray = intArrayField->GetObject(h_klass.Get())->AsIntArray();
+  Handle<mirror::IntArray> intArray =
+      hs.NewHandle(intArrayField->GetObject(h_klass.Get())->AsIntArray());
   ASSERT_TRUE(intArray != nullptr);
   ASSERT_EQ(intArray->GetLength(), 1);
   ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
 
   ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
   ASSERT_TRUE(longArrayField != nullptr);
-  mirror::LongArray* longArray = longArrayField->GetObject(h_klass.Get())->AsLongArray();
+  Handle<mirror::LongArray> longArray =
+      hs.NewHandle(longArrayField->GetObject(h_klass.Get())->AsLongArray());
   ASSERT_TRUE(longArray != nullptr);
   ASSERT_EQ(longArray->GetLength(), 1);
   ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
 
   ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
   ASSERT_TRUE(floatArrayField != nullptr);
-  mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray();
+  Handle<mirror::FloatArray> floatArray =
+      hs.NewHandle(floatArrayField->GetObject(h_klass.Get())->AsFloatArray());
   ASSERT_TRUE(floatArray != nullptr);
   ASSERT_EQ(floatArray->GetLength(), 1);
   ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
 
   ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
   ASSERT_TRUE(doubleArrayField != nullptr);
-  mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray();
+  Handle<mirror::DoubleArray> doubleArray =
+      hs.NewHandle(doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray());
   ASSERT_TRUE(doubleArray != nullptr);
   ASSERT_EQ(doubleArray->GetLength(), 1);
   ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
 
-  ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField",
-                                                                           "[Ljava/lang/Object;");
+  ArtField* objectArrayField =
+      h_klass->FindDeclaredStaticField("objectArrayField", "[Ljava/lang/Object;");
   ASSERT_TRUE(objectArrayField != nullptr);
-  mirror::ObjectArray<mirror::Object>* objectArray =
-      objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>();
+  Handle<mirror::ObjectArray<mirror::Object>> objectArray =
+      hs.NewHandle(objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>());
   ASSERT_TRUE(objectArray != nullptr);
   ASSERT_EQ(objectArray->GetLength(), 1);
   ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);