Remove static_class_ from Method/VarHandle and CallSite.

And add MethodHandle to the class roots to avoid extra
indirection through MethodHandleImpl.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 31113334
Change-Id: Iaf172f3732677f2b4509e8297e6e9af5fb81a89f
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 608e33c..151c36f 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -24,6 +24,7 @@
 #include "art_method-inl.h"
 #include "base/stringpiece.h"
 #include "class_linker-inl.h"
+#include "class_root.h"
 #include "debugger.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
@@ -47,7 +48,6 @@
 #include "runtime_callbacks.h"
 #include "scoped_thread_state_change-inl.h"
 #include "vdex_file.h"
-#include "well_known_classes.h"
 
 namespace art {
 
@@ -68,7 +68,7 @@
   if (LIKELY(!IsDefault())) {
     return this;
   } else {
-    mirror::Class* declaring_class = GetDeclaringClass();
+    ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
     DCHECK(declaring_class->IsInterface());
     ArtMethod* ret = declaring_class->FindInterfaceMethod(declaring_class->GetDexCache(),
                                                           GetDexMethodIndex(),
@@ -213,8 +213,8 @@
   if (IsStatic()) {
     return nullptr;
   }
-  mirror::Class* declaring_class = GetDeclaringClass();
-  mirror::Class* super_class = declaring_class->GetSuperClass();
+  ObjPtr<mirror::Class> declaring_class = GetDeclaringClass();
+  ObjPtr<mirror::Class> super_class = declaring_class->GetSuperClass();
   uint16_t method_index = GetMethodIndex();
   ArtMethod* result = nullptr;
   // Did this method override a super class method? If so load the result from the super class'
@@ -229,7 +229,7 @@
     } else {
       mirror::IfTable* iftable = GetDeclaringClass()->GetIfTable();
       for (size_t i = 0; i < iftable->Count() && result == nullptr; i++) {
-        mirror::Class* interface = iftable->GetInterface(i);
+        ObjPtr<mirror::Class> interface = iftable->GetInterface(i);
         for (ArtMethod& interface_method : interface->GetVirtualMethods(pointer_size)) {
           if (HasSameNameAndSignature(interface_method.GetInterfaceMethodIfProxy(pointer_size))) {
             result = &interface_method;
@@ -424,9 +424,11 @@
   if (!IsNative() || !IsVarargs()) {
     return false;
   }
-  mirror::Class* cls = GetDeclaringClass();
-  return (cls == WellKnownClasses::ToClass(WellKnownClasses::java_lang_invoke_MethodHandle) ||
-          cls == WellKnownClasses::ToClass(WellKnownClasses::java_lang_invoke_VarHandle));
+  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+      Runtime::Current()->GetClassLinker()->GetClassRoots();
+  ObjPtr<mirror::Class> cls = GetDeclaringClass();
+  return (cls == GetClassRoot<mirror::MethodHandle>(class_roots) ||
+          cls == GetClassRoot<mirror::VarHandle>(class_roots));
 }
 
 static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file,
@@ -510,7 +512,7 @@
   }
   // Although we overwrite the trampoline of non-static methods, we may get here via the resolution
   // method for direct methods (or virtual methods made direct).
-  mirror::Class* declaring_class = method->GetDeclaringClass();
+  ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
   size_t oat_method_index;
   if (method->IsStatic() || method->IsDirect()) {
     // Simple case where the oat method index was stashed at load time.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1c75fba..5d09321 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -721,55 +721,47 @@
   class_root = FindSystemClass(self, "Ljava/lang/invoke/CallSite;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeCallSite, class_root);
-  mirror::CallSite::SetClass(class_root);
 
   // Create java.lang.invoke.MethodType.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodType;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeMethodType, class_root);
-  mirror::MethodType::SetClass(class_root);
 
   // Create java.lang.invoke.MethodHandleImpl.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandleImpl;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandleImpl, class_root);
-  mirror::MethodHandleImpl::SetClass(class_root);
+  SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandle, class_root->GetSuperClass());
 
   // Create java.lang.invoke.MethodHandles.Lookup.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/MethodHandles$Lookup;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeMethodHandlesLookup, class_root);
-  mirror::MethodHandlesLookup::SetClass(class_root);
 
   // Create java.lang.invoke.VarHandle.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/VarHandle;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeVarHandle, class_root);
-  mirror::VarHandle::SetClass(class_root);
 
   // Create java.lang.invoke.FieldVarHandle.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/FieldVarHandle;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, class_root);
-  mirror::FieldVarHandle::SetClass(class_root);
 
   // Create java.lang.invoke.ArrayElementVarHandle.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/ArrayElementVarHandle;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeArrayElementVarHandle, class_root);
-  mirror::ArrayElementVarHandle::SetClass(class_root);
 
   // Create java.lang.invoke.ByteArrayViewVarHandle.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/ByteArrayViewVarHandle;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeByteArrayViewVarHandle, class_root);
-  mirror::ByteArrayViewVarHandle::SetClass(class_root);
 
   // Create java.lang.invoke.ByteBufferViewVarHandle.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/ByteBufferViewVarHandle;");
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, class_root);
-  mirror::ByteBufferViewVarHandle::SetClass(class_root);
 
   class_root = FindSystemClass(self, "Ldalvik/system/EmulatedStackFrame;");
   CHECK(class_root != nullptr);
@@ -1056,22 +1048,6 @@
   mirror::Method::SetClass(GetClassRoot(ClassRoot::kJavaLangReflectMethod, this).Ptr());
   mirror::Method::SetArrayClass(
       GetClassRoot(ClassRoot::kJavaLangReflectMethodArrayClass, this).Ptr());
-  mirror::CallSite::SetClass(GetClassRoot(ClassRoot::kJavaLangInvokeCallSite, this).Ptr());
-  mirror::MethodHandleImpl::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeMethodHandleImpl, this).Ptr());
-  mirror::MethodHandlesLookup::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeMethodHandlesLookup, this).Ptr());
-  mirror::MethodType::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeMethodType, this).Ptr());
-  mirror::VarHandle::SetClass(GetClassRoot(ClassRoot::kJavaLangInvokeVarHandle, this).Ptr());
-  mirror::FieldVarHandle::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, this).Ptr());
-  mirror::ArrayElementVarHandle::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeArrayElementVarHandle, this).Ptr());
-  mirror::ByteArrayViewVarHandle::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeByteArrayViewVarHandle, this).Ptr());
-  mirror::ByteBufferViewVarHandle::SetClass(
-      GetClassRoot(ClassRoot::kJavaLangInvokeByteBufferViewVarHandle, this).Ptr());
   mirror::Reference::SetClass(GetClassRoot(ClassRoot::kJavaLangRefReference, this));
   mirror::Throwable::SetClass(GetClassRoot(ClassRoot::kJavaLangThrowable, this));
   mirror::StackTraceElement::SetClass(GetClassRoot(ClassRoot::kJavaLangStackTraceElement, this));
@@ -2166,15 +2142,6 @@
   mirror::Constructor::ResetArrayClass();
   mirror::Field::ResetArrayClass();
   mirror::Method::ResetArrayClass();
-  mirror::CallSite::ResetClass();
-  mirror::MethodType::ResetClass();
-  mirror::MethodHandleImpl::ResetClass();
-  mirror::MethodHandlesLookup::ResetClass();
-  mirror::VarHandle::ResetClass();
-  mirror::FieldVarHandle::ResetClass();
-  mirror::ArrayElementVarHandle::ResetClass();
-  mirror::ByteArrayViewVarHandle::ResetClass();
-  mirror::ByteBufferViewVarHandle::ResetClass();
   mirror::EmulatedStackFrame::ResetClass();
   Thread* const self = Thread::Current();
   for (const ClassLoaderData& data : class_loaders_) {
diff --git a/runtime/class_root.h b/runtime/class_root.h
index f43e2c6..5c78198 100644
--- a/runtime/class_root.h
+++ b/runtime/class_root.h
@@ -68,6 +68,7 @@
   M(kJavaLangReflectFieldArrayClass,        "[Ljava/lang/reflect/Field;",                 mirror::ObjectArray<mirror::Field>)                       \
   M(kJavaLangReflectMethodArrayClass,       "[Ljava/lang/reflect/Method;",                mirror::ObjectArray<mirror::Method>)                      \
   M(kJavaLangInvokeCallSite,                "Ljava/lang/invoke/CallSite;",                mirror::CallSite)                                         \
+  M(kJavaLangInvokeMethodHandle,            "Ljava/lang/invoke/MethodHandle;",            mirror::MethodHandle)                                     \
   M(kJavaLangInvokeMethodHandleImpl,        "Ljava/lang/invoke/MethodHandleImpl;",        mirror::MethodHandleImpl)                                 \
   M(kJavaLangInvokeMethodHandlesLookup,     "Ljava/lang/invoke/MethodHandles$Lookup;",    mirror::MethodHandlesLookup)                              \
   M(kJavaLangInvokeMethodType,              "Ljava/lang/invoke/MethodType;",              mirror::MethodType)                                       \
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 0985bf2..a59faea 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -19,6 +19,7 @@
 #include "base/enums.h"
 #include "callee_save_frame.h"
 #include "common_throws.h"
+#include "class_root.h"
 #include "debug_print.h"
 #include "debugger.h"
 #include "dex/dex_file-inl.h"
@@ -2810,7 +2811,7 @@
   RangeInstructionOperands operands(first_arg + 1, num_vregs - 1);
   Intrinsics intrinsic = static_cast<Intrinsics>(resolved_method->GetIntrinsic());
   bool success = false;
-  if (resolved_method->GetDeclaringClass() == mirror::MethodHandle::StaticClass()) {
+  if (resolved_method->GetDeclaringClass() == GetClassRoot<mirror::MethodHandle>(linker)) {
     Handle<mirror::MethodHandle> method_handle(hs.NewHandle(
         ObjPtr<mirror::MethodHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
     if (intrinsic == Intrinsics::kMethodHandleInvokeExact) {
@@ -2831,7 +2832,7 @@
                                    result);
     }
   } else {
-    DCHECK_EQ(mirror::VarHandle::StaticClass(), resolved_method->GetDeclaringClass());
+    DCHECK_EQ(GetClassRoot<mirror::VarHandle>(linker), resolved_method->GetDeclaringClass());
     Handle<mirror::VarHandle> var_handle(hs.NewHandle(
         ObjPtr<mirror::VarHandle>::DownCast(MakeObjPtr(receiver_handle.Get()))));
     mirror::VarHandle::AccessMode access_mode =
diff --git a/runtime/image.cc b/runtime/image.cc
index 316f7a5..7ad2e7b 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -26,7 +26,7 @@
 namespace art {
 
 const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '5', '9', '\0' };  // ReachabilityFence.
+const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '0', '\0' };  // ClassRoot::MethodHandle.
 
 ImageHeader::ImageHeader(uint32_t image_begin,
                          uint32_t image_size,
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 708a788..fab3509 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -19,6 +19,7 @@
 #include <cmath>
 
 #include "base/enums.h"
+#include "class_root.h"
 #include "debugger.h"
 #include "dex/dex_file_types.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
@@ -865,6 +866,7 @@
 static ObjPtr<mirror::Class> GetClassForBootstrapArgument(EncodedArrayValueIterator::ValueType type)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = class_linker->GetClassRoots();
   switch (type) {
     case EncodedArrayValueIterator::ValueType::kBoolean:
     case EncodedArrayValueIterator::ValueType::kByte:
@@ -874,21 +876,21 @@
       // will result in CCE's being raised if the BSM has one of these
       // types.
     case EncodedArrayValueIterator::ValueType::kInt:
-      return class_linker->FindPrimitiveClass('I');
+      return GetClassRoot(ClassRoot::kPrimitiveInt, class_roots);
     case EncodedArrayValueIterator::ValueType::kLong:
-      return class_linker->FindPrimitiveClass('J');
+      return GetClassRoot(ClassRoot::kPrimitiveLong, class_roots);
     case EncodedArrayValueIterator::ValueType::kFloat:
-      return class_linker->FindPrimitiveClass('F');
+      return GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots);
     case EncodedArrayValueIterator::ValueType::kDouble:
-      return class_linker->FindPrimitiveClass('D');
+      return GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots);
     case EncodedArrayValueIterator::ValueType::kMethodType:
-      return mirror::MethodType::StaticClass();
+      return GetClassRoot<mirror::MethodType>(class_roots);
     case EncodedArrayValueIterator::ValueType::kMethodHandle:
-      return mirror::MethodHandle::StaticClass();
+      return GetClassRoot<mirror::MethodHandle>(class_roots);
     case EncodedArrayValueIterator::ValueType::kString:
-      return mirror::String::GetJavaLangString();
+      return GetClassRoot<mirror::String>();
     case EncodedArrayValueIterator::ValueType::kType:
-      return mirror::Class::GetJavaLangClass();
+      return GetClassRoot<mirror::Class>();
     case EncodedArrayValueIterator::ValueType::kField:
     case EncodedArrayValueIterator::ValueType::kMethod:
     case EncodedArrayValueIterator::ValueType::kEnum:
@@ -1091,21 +1093,23 @@
   setter->SetReference(array.Get());                                    \
   return true;
 
-  if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('I')) {
+  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots = class_linker->GetClassRoots();
+  ObjPtr<mirror::Class> component_type = array_type->GetComponentType();
+  if (component_type == GetClassRoot(ClassRoot::kPrimitiveInt, class_roots)) {
     COLLECT_PRIMITIVE_ARRAY(I, Int);
-  } else if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('J')) {
+  } else if (component_type == GetClassRoot(ClassRoot::kPrimitiveLong, class_roots)) {
     COLLECT_PRIMITIVE_ARRAY(J, Long);
-  } else if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('F')) {
+  } else if (component_type == GetClassRoot(ClassRoot::kPrimitiveFloat, class_roots)) {
     COLLECT_PRIMITIVE_ARRAY(F, Float);
-  } else if (array_type->GetComponentType() == class_linker->FindPrimitiveClass('D')) {
+  } else if (component_type == GetClassRoot(ClassRoot::kPrimitiveDouble, class_roots)) {
     COLLECT_PRIMITIVE_ARRAY(D, Double);
-  } else if (array_type->GetComponentType() == mirror::MethodType::StaticClass()) {
+  } else if (component_type == GetClassRoot<mirror::MethodType>()) {
     COLLECT_REFERENCE_ARRAY(mirror::MethodType, MethodType);
-  } else if (array_type->GetComponentType() == mirror::MethodHandle::StaticClass()) {
+  } else if (component_type == GetClassRoot<mirror::MethodHandle>()) {
     COLLECT_REFERENCE_ARRAY(mirror::MethodHandle, MethodHandle);
-  } else if (array_type->GetComponentType() == mirror::String::GetJavaLangString()) {
+  } else if (component_type == GetClassRoot<mirror::String>(class_roots)) {
     COLLECT_REFERENCE_ARRAY(mirror::String, String);
-  } else if (array_type->GetComponentType() == mirror::Class::GetJavaLangClass()) {
+  } else if (component_type == GetClassRoot<mirror::Class>()) {
     COLLECT_REFERENCE_ARRAY(mirror::Class, Type);
   } else {
     UNREACHABLE();
@@ -1125,8 +1129,8 @@
   StackHandleScope<2> hs(self);
   // Create array for parameter types.
   ObjPtr<mirror::Class> class_type = mirror::Class::GetJavaLangClass();
-  mirror::Class* class_array_type =
-      Runtime::Current()->GetClassLinker()->FindArrayClass(self, &class_type);
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  ObjPtr<mirror::Class> class_array_type = class_linker->FindArrayClass(self, &class_type);
   Handle<mirror::ObjectArray<mirror::Class>> ptypes = hs.NewHandle(
       mirror::ObjectArray<mirror::Class>::Alloc(self,
                                                 class_array_type,
@@ -1138,7 +1142,7 @@
 
   // Populate the first argument with an instance of j.l.i.MethodHandles.Lookup
   // that the runtime will construct.
-  ptypes->Set(0, mirror::MethodHandlesLookup::StaticClass());
+  ptypes->Set(0, GetClassRoot<mirror::MethodHandlesLookup>(class_linker));
   it.Next();
 
   // The remaining parameter types are derived from the types of
@@ -1157,7 +1161,7 @@
   DCHECK_EQ(static_cast<size_t>(index), it.Size());
 
   // By definition, the return type is always a j.l.i.CallSite.
-  Handle<mirror::Class> rtype = hs.NewHandle(mirror::CallSite::StaticClass());
+  Handle<mirror::Class> rtype = hs.NewHandle(GetClassRoot<mirror::CallSite>());
   return mirror::MethodType::Create(self, rtype, ptypes);
 }
 
@@ -1352,8 +1356,9 @@
   }
 
   // Check the result type is a subclass of j.l.i.CallSite.
-  if (UNLIKELY(!object->InstanceOf(mirror::CallSite::StaticClass()))) {
-    ThrowClassCastException(object->GetClass(), mirror::CallSite::StaticClass());
+  ObjPtr<mirror::Class> call_site_class = GetClassRoot<mirror::CallSite>(class_linker);
+  if (UNLIKELY(!object->InstanceOf(call_site_class))) {
+    ThrowClassCastException(object->GetClass(), call_site_class);
     return nullptr;
   }
 
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 5d4b9e8..9c02dce 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -24,6 +24,7 @@
 #include "base/memory_tool.h"
 #include "base/runtime_debug.h"
 #include "base/utils.h"
+#include "class_root.h"
 #include "debugger.h"
 #include "entrypoints/runtime_asm_entrypoints.h"
 #include "interpreter/interpreter.h"
@@ -632,7 +633,8 @@
   }
   if (method->IsNative()) {
     ObjPtr<mirror::Class> klass = method->GetDeclaringClass();
-    if (klass == mirror::MethodHandle::StaticClass() || klass == mirror::VarHandle::StaticClass()) {
+    if (klass == GetClassRoot<mirror::MethodHandle>() ||
+        klass == GetClassRoot<mirror::VarHandle>()) {
       // MethodHandle and VarHandle invocation methods are required to throw an
       // UnsupportedOperationException if invoked reflectively. We achieve this by having native
       // implementations that arise the exception. We need to disable JIT compilation of these JNI
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 27de725..28df174 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -18,6 +18,7 @@
 
 #include "android-base/stringprintf.h"
 
+#include "class_root.h"
 #include "common_dex_operations.h"
 #include "interpreter/shadow_frame-inl.h"
 #include "jvalue-inl.h"
@@ -1022,7 +1023,7 @@
   // Check that the first parameter is a VarHandle
   if (callsite_ptypes->GetLength() < 1 ||
       !mh_ptypes->Get(0)->IsAssignableFrom(callsite_ptypes->Get(0)) ||
-      mh_ptypes->Get(0) != mirror::VarHandle::StaticClass()) {
+      mh_ptypes->Get(0) != GetClassRoot<mirror::VarHandle>()) {
     ThrowWrongMethodTypeException(method_handle->GetMethodType(), callsite_type.Get());
     return false;
   }
@@ -1036,7 +1037,7 @@
 
   // Cast to VarHandle instance
   Handle<mirror::VarHandle> vh(hs.NewHandle(down_cast<mirror::VarHandle*>(receiver)));
-  DCHECK(mirror::VarHandle::StaticClass()->IsAssignableFrom(vh->GetClass()));
+  DCHECK(GetClassRoot<mirror::VarHandle>()->IsAssignableFrom(vh->GetClass()));
 
   // Determine the accessor kind to dispatch
   ArtMethod* target_method = method_handle->GetTargetMethod();
diff --git a/runtime/mirror/call_site.cc b/runtime/mirror/call_site.cc
index eb613df..808f77c 100644
--- a/runtime/mirror/call_site.cc
+++ b/runtime/mirror/call_site.cc
@@ -17,36 +17,20 @@
 #include "call_site.h"
 
 #include "class-inl.h"
+#include "class_root.h"
 #include "gc_root-inl.h"
 
 namespace art {
 namespace mirror {
 
-GcRoot<mirror::Class> CallSite::static_class_;
-
 mirror::CallSite* CallSite::Create(Thread* const self, Handle<MethodHandle> target) {
   StackHandleScope<1> hs(self);
   Handle<mirror::CallSite> cs(
-      hs.NewHandle(ObjPtr<CallSite>::DownCast(StaticClass()->AllocObject(self))));
+      hs.NewHandle(ObjPtr<CallSite>::DownCast(GetClassRoot<CallSite>()->AllocObject(self))));
   CHECK(!Runtime::Current()->IsActiveTransaction());
   cs->SetFieldObject<false>(TargetOffset(), target.Get());
   return cs.Get();
 }
 
-void CallSite::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void CallSite::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void CallSite::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/call_site.h b/runtime/mirror/call_site.h
index 93f2748..9b6afca 100644
--- a/runtime/mirror/call_site.h
+++ b/runtime/mirror/call_site.h
@@ -33,18 +33,10 @@
                                   Handle<MethodHandle> method_handle)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-    return static_class_.Read();
-  }
-
   MethodHandle* GetTarget() REQUIRES_SHARED(Locks::mutator_lock_) {
     return GetFieldObject<MethodHandle>(TargetOffset());
   }
 
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   static inline MemberOffset TargetOffset() {
     return MemberOffset(OFFSETOF_MEMBER(CallSite, target_));
@@ -52,8 +44,6 @@
 
   HeapReference<mirror::MethodHandle> target_;
 
-  static GcRoot<mirror::Class> static_class_;  // java.lang.invoke.CallSite.class
-
   friend struct art::CallSiteOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(CallSite);
 };
diff --git a/runtime/mirror/method_handle_impl.cc b/runtime/mirror/method_handle_impl.cc
index 0b4dde1..a6c1609 100644
--- a/runtime/mirror/method_handle_impl.cc
+++ b/runtime/mirror/method_handle_impl.cc
@@ -17,6 +17,7 @@
 #include "method_handle_impl-inl.h"
 
 #include "class-inl.h"
+#include "class_root.h"
 #include "gc_root-inl.h"
 
 namespace art {
@@ -30,12 +31,6 @@
   }
 }
 
-mirror::Class* MethodHandle::StaticClass() {
-  mirror::Class* klass = MethodHandleImpl::StaticClass()->GetSuperClass();
-  DCHECK(klass->DescriptorEquals("Ljava/lang/invoke/MethodHandle;"));
-  return klass;
-}
-
 void MethodHandle::Initialize(uintptr_t art_field_or_method,
                               Kind kind,
                               Handle<MethodType> method_type)
@@ -48,35 +43,14 @@
   SetField64<false>(ArtFieldOrMethodOffset(), art_field_or_method);
 }
 
-GcRoot<mirror::Class> MethodHandleImpl::static_class_;
-
-mirror::Class* MethodHandleImpl::StaticClass()  {
-  return static_class_.Read();
-}
-
-void MethodHandleImpl::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void MethodHandleImpl::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void MethodHandleImpl::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
 mirror::MethodHandleImpl* MethodHandleImpl::Create(Thread* const self,
                                                    uintptr_t art_field_or_method,
                                                    MethodHandle::Kind kind,
                                                    Handle<MethodType> method_type)
     REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
   StackHandleScope<1> hs(self);
-  Handle<mirror::MethodHandleImpl> mh(
-      hs.NewHandle(ObjPtr<MethodHandleImpl>::DownCast(StaticClass()->AllocObject(self))));
+  Handle<mirror::MethodHandleImpl> mh(hs.NewHandle(ObjPtr<MethodHandleImpl>::DownCast(
+      GetClassRoot<MethodHandleImpl>()->AllocObject(self))));
   mh->Initialize(art_field_or_method, kind, method_type);
   return mh.Get();
 }
diff --git a/runtime/mirror/method_handle_impl.h b/runtime/mirror/method_handle_impl.h
index 3b0002c..4813b3c 100644
--- a/runtime/mirror/method_handle_impl.h
+++ b/runtime/mirror/method_handle_impl.h
@@ -87,8 +87,6 @@
   // supported.
   static const char* GetReturnTypeDescriptor(const char* invoke_method_name);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
  protected:
   void Initialize(uintptr_t art_field_or_method, Kind kind, Handle<MethodType> method_type)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -130,19 +128,12 @@
                                           Handle<MethodType> method_type)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   static MemberOffset InfoOffset() {
     return MemberOffset(OFFSETOF_MEMBER(MethodHandleImpl, info_));
   }
 
   HeapReference<mirror::Object> info_;  // Unused by the runtime.
-  static GcRoot<mirror::Class> static_class_;  // java.lang.invoke.MethodHandleImpl.class
 
   friend struct art::MethodHandleImplOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandleImpl);
diff --git a/runtime/mirror/method_handles_lookup.cc b/runtime/mirror/method_handles_lookup.cc
index aeecf75..1ac38da 100644
--- a/runtime/mirror/method_handles_lookup.cc
+++ b/runtime/mirror/method_handles_lookup.cc
@@ -17,6 +17,7 @@
 #include "method_handles_lookup.h"
 
 #include "class-inl.h"
+#include "class_root.h"
 #include "dex/modifiers.h"
 #include "gc_root-inl.h"
 #include "handle_scope.h"
@@ -28,33 +29,15 @@
 namespace art {
 namespace mirror {
 
-GcRoot<mirror::Class> MethodHandlesLookup::static_class_;
-
-void MethodHandlesLookup::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void MethodHandlesLookup::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void MethodHandlesLookup::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
 MethodHandlesLookup* MethodHandlesLookup::Create(Thread* const self, Handle<Class> lookup_class)
   REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
   static constexpr uint32_t kAllModes = kAccPublic | kAccPrivate | kAccProtected | kAccStatic;
 
-  StackHandleScope<1> hs(self);
-  Handle<MethodHandlesLookup> mhl(
-      hs.NewHandle(ObjPtr<MethodHandlesLookup>::DownCast(StaticClass()->AllocObject(self))));
+  ObjPtr<MethodHandlesLookup> mhl = ObjPtr<MethodHandlesLookup>::DownCast(
+      GetClassRoot<MethodHandlesLookup>()->AllocObject(self));
   mhl->SetFieldObject<false>(LookupClassOffset(), lookup_class.Get());
   mhl->SetField32<false>(AllowedModesOffset(), kAllModes);
-  return mhl.Get();
+  return mhl.Ptr();
 }
 
 MethodHandlesLookup* MethodHandlesLookup::GetDefault(Thread* const self) {
diff --git a/runtime/mirror/method_handles_lookup.h b/runtime/mirror/method_handles_lookup.h
index fefcb2e..aa94f95 100644
--- a/runtime/mirror/method_handles_lookup.h
+++ b/runtime/mirror/method_handles_lookup.h
@@ -40,14 +40,6 @@
                                              Handle<Class> lookup_class)
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-    return static_class_.Read();
-  }
-
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Returns the result of java.lang.invoke.MethodHandles.lookup().
   static mirror::MethodHandlesLookup* GetDefault(Thread* const self)
       REQUIRES_SHARED(Locks::mutator_lock_);
@@ -71,8 +63,6 @@
 
   int32_t allowed_modes_;
 
-  static GcRoot<mirror::Class> static_class_;  // java.lang.invoke.MethodHandles.Lookup.class
-
   friend struct art::MethodHandlesLookupOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodHandlesLookup);
 };
diff --git a/runtime/mirror/method_type.cc b/runtime/mirror/method_type.cc
index 45f7a87..a8be8b7 100644
--- a/runtime/mirror/method_type.cc
+++ b/runtime/mirror/method_type.cc
@@ -17,6 +17,7 @@
 #include "method_type.h"
 
 #include "class-inl.h"
+#include "class_root.h"
 #include "gc_root-inl.h"
 #include "method_handles.h"
 
@@ -35,14 +36,12 @@
 
 }  // namespace
 
-GcRoot<Class> MethodType::static_class_;
-
 MethodType* MethodType::Create(Thread* const self,
                                Handle<Class> return_type,
                                Handle<ObjectArray<Class>> parameter_types) {
   StackHandleScope<1> hs(self);
   Handle<MethodType> mt(
-      hs.NewHandle(ObjPtr<MethodType>::DownCast(StaticClass()->AllocObject(self))));
+      hs.NewHandle(ObjPtr<MethodType>::DownCast(GetClassRoot<MethodType>()->AllocObject(self))));
 
   // TODO: Do we ever create a MethodType during a transaction ? There doesn't
   // seem like a good reason to do a polymorphic invoke that results in the
@@ -172,20 +171,5 @@
   return ss.str();
 }
 
-void MethodType::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void MethodType::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void MethodType::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/method_type.h b/runtime/mirror/method_type.h
index 771162a..014b211 100644
--- a/runtime/mirror/method_type.h
+++ b/runtime/mirror/method_type.h
@@ -48,10 +48,6 @@
                                               int32_t start_index)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-    return static_class_.Read();
-  }
-
   ObjectArray<Class>* GetPTypes() REQUIRES_SHARED(Locks::mutator_lock_) {
     return GetFieldObject<ObjectArray<Class>>(OFFSET_OF_OBJECT_MEMBER(MethodType, p_types_));
   }
@@ -68,10 +64,6 @@
     return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(MethodType, r_type_));
   }
 
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
   // Returns true iff. |this| is an exact match for method type |target|, i.e
   // iff. they have the same return types and parameter types.
   bool IsExactMatch(MethodType* target) REQUIRES_SHARED(Locks::mutator_lock_);
@@ -111,8 +103,6 @@
   HeapReference<Class> r_type_;
   HeapReference<Object> wrap_alt_;  // Unused in the runtime
 
-  static GcRoot<Class> static_class_;  // java.lang.invoke.MethodType.class
-
   friend struct art::MethodTypeOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(MethodType);
 };
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index c755299..8311d91 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -20,6 +20,7 @@
 #include "art_field-inl.h"
 #include "class-inl.h"
 #include "class_linker.h"
+#include "class_root.h"
 #include "gc_root-inl.h"
 #include "intrinsics_enum.h"
 #include "jni/jni_internal.h"
@@ -1580,17 +1581,18 @@
                        ShadowFrame* shadow_frame,
                        const InstructionOperands* const operands,
                        JValue* result) {
-  Class* klass = GetClass();
-  if (klass == FieldVarHandle::StaticClass()) {
+  ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
+  ObjPtr<Class> klass = GetClass();
+  if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
     auto vh = reinterpret_cast<FieldVarHandle*>(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
-  } else if (klass == ArrayElementVarHandle::StaticClass()) {
+  } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
     auto vh = reinterpret_cast<ArrayElementVarHandle*>(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
-  } else if (klass == ByteArrayViewVarHandle::StaticClass()) {
+  } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
     auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
-  } else if (klass == ByteBufferViewVarHandle::StaticClass()) {
+  } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
     auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
   } else {
@@ -1681,27 +1683,6 @@
   return true;
 }
 
-Class* VarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-  return static_class_.Read();
-}
-
-void VarHandle::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void VarHandle::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void VarHandle::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> VarHandle::static_class_;
-
 ArtField* FieldVarHandle::GetField() {
   uintptr_t opaque_field = static_cast<uintptr_t>(GetField64(ArtFieldOffset()));
   return reinterpret_cast<ArtField*>(opaque_field);
@@ -1758,27 +1739,6 @@
   UNREACHABLE();
 }
 
-Class* FieldVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-  return static_class_.Read();
-}
-
-void FieldVarHandle::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void FieldVarHandle::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void FieldVarHandle::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> FieldVarHandle::static_class_;
-
 bool ArrayElementVarHandle::Access(AccessMode access_mode,
                                    ShadowFrame* shadow_frame,
                                    const InstructionOperands* const operands,
@@ -1867,27 +1827,6 @@
   UNREACHABLE();
 }
 
-Class* ArrayElementVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-  return static_class_.Read();
-}
-
-void ArrayElementVarHandle::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void ArrayElementVarHandle::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void ArrayElementVarHandle::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> ArrayElementVarHandle::static_class_;
-
 bool ByteArrayViewVarHandle::GetNativeByteOrder() {
   return GetFieldBoolean(NativeByteOrderOffset());
 }
@@ -1976,27 +1915,6 @@
   UNREACHABLE();
 }
 
-Class* ByteArrayViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-  return static_class_.Read();
-}
-
-void ByteArrayViewVarHandle::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void ByteArrayViewVarHandle::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void ByteArrayViewVarHandle::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> ByteArrayViewVarHandle::static_class_;
-
 bool ByteBufferViewVarHandle::GetNativeByteOrder() {
   return GetFieldBoolean(NativeByteOrderOffset());
 }
@@ -2117,26 +2035,5 @@
   UNREACHABLE();
 }
 
-Class* ByteBufferViewVarHandle::StaticClass() REQUIRES_SHARED(Locks::mutator_lock_) {
-  return static_class_.Read();
-}
-
-void ByteBufferViewVarHandle::SetClass(Class* klass) {
-  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
-  CHECK(klass != nullptr);
-  static_class_ = GcRoot<Class>(klass);
-}
-
-void ByteBufferViewVarHandle::ResetClass() {
-  CHECK(!static_class_.IsNull());
-  static_class_ = GcRoot<Class>(nullptr);
-}
-
-void ByteBufferViewVarHandle::VisitRoots(RootVisitor* visitor) {
-  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
-}
-
-GcRoot<Class> ByteBufferViewVarHandle::static_class_;
-
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index 5186d43..4fd18c1 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -149,11 +149,6 @@
   // VarHandle access method, such as "setOpaque". Returns false otherwise.
   static bool GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   Class* GetCoordinateType0() REQUIRES_SHARED(Locks::mutator_lock_);
   Class* GetCoordinateType1() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -185,9 +180,6 @@
   HeapReference<mirror::Class> var_type_;
   int32_t access_modes_bit_mask_;
 
-  // Root representing java.lang.invoke.VarHandle.class.
-  static GcRoot<mirror::Class> static_class_;
-
   friend class VarHandleTest;  // for testing purposes
   friend struct art::VarHandleOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(VarHandle);
@@ -218,9 +210,6 @@
   // ArtField instance corresponding to variable for accessors.
   int64_t art_field_;
 
-  // Root representing java.lang.invoke.FieldVarHandle.class.
-  static GcRoot<mirror::Class> static_class_;
-
   friend class VarHandleTest;  // for var_handle_test.
   friend struct art::FieldVarHandleOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle);
@@ -236,15 +225,7 @@
                 JValue* result)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
-  // Root representing java.lang.invoke.ArrayElementVarHandle.class.
-  static GcRoot<mirror::Class> static_class_;
-
   friend class VarHandleTest;
   DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayElementVarHandle);
 };
@@ -261,11 +242,6 @@
 
   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   static MemberOffset NativeByteOrderOffset() {
     return MemberOffset(OFFSETOF_MEMBER(ByteArrayViewVarHandle, native_byte_order_));
@@ -274,9 +250,6 @@
   // Flag indicating that accessors should use native byte-ordering.
   uint8_t native_byte_order_;
 
-  // Root representing java.lang.invoke.ByteArrayViewVarHandle.class.
-  static GcRoot<mirror::Class> static_class_;
-
   friend class VarHandleTest;  // for var_handle_test.
   friend struct art::ByteArrayViewVarHandleOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteArrayViewVarHandle);
@@ -294,11 +267,6 @@
 
   bool GetNativeByteOrder() REQUIRES_SHARED(Locks::mutator_lock_);
 
-  static mirror::Class* StaticClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void SetClass(Class* klass) REQUIRES_SHARED(Locks::mutator_lock_);
-  static void ResetClass() REQUIRES_SHARED(Locks::mutator_lock_);
-  static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
-
  private:
   bool AccessHeapBuffer(AccessMode access_mode,
                         ObjPtr<Object> byte_buffer,
@@ -322,9 +290,6 @@
   // Flag indicating that accessors should use native byte-ordering.
   uint8_t native_byte_order_;
 
-  // Root representing java.lang.invoke.ByteBufferViewVarHandle.class.
-  static GcRoot<mirror::Class> static_class_;
-
   friend class VarHandleTest;  // for var_handle_test.
   friend struct art::ByteBufferViewVarHandleOffsets;  // for verifying offset information
   DISALLOW_IMPLICIT_CONSTRUCTORS(ByteBufferViewVarHandle);
diff --git a/runtime/mirror/var_handle_test.cc b/runtime/mirror/var_handle_test.cc
index 005aba3..2c12832 100644
--- a/runtime/mirror/var_handle_test.cc
+++ b/runtime/mirror/var_handle_test.cc
@@ -23,6 +23,7 @@
 #include "class-inl.h"
 #include "class_linker-inl.h"
 #include "class_loader.h"
+#include "class_root.h"
 #include "common_runtime_test.h"
 #include "handle_scope-inl.h"
 #include "jvalue-inl.h"
@@ -43,7 +44,7 @@
       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_) {
     StackHandleScope<4> hs(self);
     Handle<FieldVarHandle> fvh = hs.NewHandle(
-        ObjPtr<FieldVarHandle>::DownCast(FieldVarHandle::StaticClass()->AllocObject(self)));
+        ObjPtr<FieldVarHandle>::DownCast(GetClassRoot<FieldVarHandle>()->AllocObject(self)));
     Handle<Class> var_type = hs.NewHandle(art_field->ResolveType());
 
     if (art_field->IsStatic()) {
@@ -67,7 +68,7 @@
     StackHandleScope<3> hs(self);
     Handle<ArrayElementVarHandle> vh = hs.NewHandle(
         ObjPtr<ArrayElementVarHandle>::DownCast(
-            ArrayElementVarHandle::StaticClass()->AllocObject(self)));
+            GetClassRoot<ArrayElementVarHandle>()->AllocObject(self)));
 
     // Initialize super class fields
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -85,7 +86,7 @@
     StackHandleScope<4> hs(self);
     Handle<ByteArrayViewVarHandle> bvh = hs.NewHandle(
         ObjPtr<ByteArrayViewVarHandle>::DownCast(
-            ByteArrayViewVarHandle::StaticClass()->AllocObject(self)));
+            GetClassRoot<ByteArrayViewVarHandle>()->AllocObject(self)));
 
     // Initialize super class fields
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -106,7 +107,7 @@
     StackHandleScope<5> hs(self);
     Handle<ByteBufferViewVarHandle> bvh = hs.NewHandle(
         ObjPtr<ByteBufferViewVarHandle>::DownCast(
-            ByteArrayViewVarHandle::StaticClass()->AllocObject(self)));
+            GetClassRoot<ByteArrayViewVarHandle>()->AllocObject(self)));
     // Initialize super class fields
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     Handle<Class> var_type = hs.NewHandle(view_array_class->GetComponentType());
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 9f595b1..b7dad89 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -22,6 +22,7 @@
 #include "art_method-inl.h"
 #include "base/enums.h"
 #include "class_linker-inl.h"
+#include "class_root.h"
 #include "common_throws.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
@@ -82,7 +83,7 @@
         // is subject to change so conservatively cover the entire package.
         // NB Static initializers within java.lang.invoke are permitted and do not
         // need further stack inspection.
-        ObjPtr<mirror::Class> lookup_class = mirror::MethodHandlesLookup::StaticClass();
+        ObjPtr<mirror::Class> lookup_class = GetClassRoot<mirror::MethodHandlesLookup>();
         if ((declaring_class == lookup_class || declaring_class->IsInSamePackage(lookup_class))
             && !m->IsClassInitializer()) {
           return true;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 621eec5..d126fe9 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1984,17 +1984,8 @@
   mirror::String::VisitRoots(visitor);
   mirror::Throwable::VisitRoots(visitor);
   mirror::Field::VisitRoots(visitor);
-  mirror::MethodType::VisitRoots(visitor);
-  mirror::MethodHandleImpl::VisitRoots(visitor);
-  mirror::MethodHandlesLookup::VisitRoots(visitor);
   mirror::EmulatedStackFrame::VisitRoots(visitor);
   mirror::ClassExt::VisitRoots(visitor);
-  mirror::CallSite::VisitRoots(visitor);
-  mirror::VarHandle::VisitRoots(visitor);
-  mirror::FieldVarHandle::VisitRoots(visitor);
-  mirror::ArrayElementVarHandle::VisitRoots(visitor);
-  mirror::ByteArrayViewVarHandle::VisitRoots(visitor);
-  mirror::ByteBufferViewVarHandle::VisitRoots(visitor);
   // Visiting the roots of these ArtMethods is not currently required since all the GcRoots are
   // null.
   BufferedRootVisitor<16> buffered_visitor(visitor, RootInfo(kRootVMInternal));
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 91cec23..3a49e4d 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -33,6 +33,7 @@
 #include "base/time_utils.h"
 #include "base/utils.h"
 #include "class_linker.h"
+#include "class_root.h"
 #include "compiler_callbacks.h"
 #include "dex/descriptors_names.h"
 #include "dex/dex_file-inl.h"
@@ -4206,9 +4207,11 @@
   const char* method_name = method->GetName();
 
   const char* expected_return_descriptor;
-  if (klass == mirror::MethodHandle::StaticClass()) {
+  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+      Runtime::Current()->GetClassLinker()->GetClassRoots();
+  if (klass == GetClassRoot<mirror::MethodHandle>(class_roots)) {
     expected_return_descriptor = mirror::MethodHandle::GetReturnTypeDescriptor(method_name);
-  } else if (klass == mirror::VarHandle::StaticClass()) {
+  } else if (klass == GetClassRoot<mirror::VarHandle>(class_roots)) {
     expected_return_descriptor = mirror::VarHandle::GetReturnTypeDescriptor(method_name);
   } else {
     Fail(VERIFY_ERROR_BAD_CLASS_HARD)
@@ -4268,12 +4271,16 @@
         << "invoke-polymorphic receiver has no class: "
         << this_type;
     return false;
-  } else if (!this_type.GetClass()->IsSubClass(mirror::MethodHandle::StaticClass()) &&
-             !this_type.GetClass()->IsSubClass(mirror::VarHandle::StaticClass())) {
-    Fail(VERIFY_ERROR_BAD_CLASS_HARD)
-        << "invoke-polymorphic receiver is not a subclass of MethodHandle or VarHandle: "
-        << this_type;
-    return false;
+  } else {
+    ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
+        Runtime::Current()->GetClassLinker()->GetClassRoots();
+    if (!this_type.GetClass()->IsSubClass(GetClassRoot<mirror::MethodHandle>(class_roots)) &&
+        !this_type.GetClass()->IsSubClass(GetClassRoot<mirror::VarHandle>(class_roots))) {
+      Fail(VERIFY_ERROR_BAD_CLASS_HARD)
+          << "invoke-polymorphic receiver is not a subclass of MethodHandle or VarHandle: "
+          << this_type;
+      return false;
+    }
   }
   return true;
 }
diff --git a/runtime/verifier/reg_type_cache-inl.h b/runtime/verifier/reg_type_cache-inl.h
index 61f34af..43c0ab9 100644
--- a/runtime/verifier/reg_type_cache-inl.h
+++ b/runtime/verifier/reg_type_cache-inl.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_VERIFIER_REG_TYPE_CACHE_INL_H_
 
 #include "class_linker.h"
+#include "class_root.h"
 #include "mirror/class-inl.h"
 #include "mirror/method_handle_impl.h"
 #include "mirror/method_type.h"
@@ -138,14 +139,14 @@
 
 inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodHandle() {
   const RegType* result = &FromClass("Ljava/lang/invoke/MethodHandle;",
-                                     mirror::MethodHandle::StaticClass(), true);
+                                     GetClassRoot<mirror::MethodHandle>().Ptr(), true);
   DCHECK(result->IsPreciseReference());
   return *down_cast<const PreciseReferenceType*>(result);
 }
 
 inline const PreciseReferenceType& RegTypeCache::JavaLangInvokeMethodType() {
   const RegType* result = &FromClass("Ljava/lang/invoke/MethodType;",
-                                     mirror::MethodType::StaticClass(), true);
+                                     GetClassRoot<mirror::MethodType>().Ptr(), true);
   DCHECK(result->IsPreciseReference());
   return *down_cast<const PreciseReferenceType*>(result);
 }