ART: Ensure dex caches keep classloader live

Live dex caches must keep their associated classloader live. Otherwise
the classloader may get unloaded, attempting to free DexFiles which
cannot be unregistered.

Test: art/test/testrunner/testrunner.py -b --host
Test: m test-art-host-gtest
Change-Id: I0eed5b3b46ed681c739d6923a57d0878afbba1a7
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 73b8166..3919204 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4025,6 +4025,8 @@
   // Make sure to hold the dex cache live in the class table. This case happens for the boot class
   // path dex caches without an image.
   data.class_table->InsertStrongRoot(dex_cache);
+  // Make sure that the dex cache holds the classloader live.
+  dex_cache->SetClassLoader(class_loader);
   if (class_loader != nullptr) {
     // Since we added a strong root to the class table, do the write barrier as required for
     // remembered sets and generational GCs.
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 1e501a7..931f6df 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -672,6 +672,7 @@
 
 struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> {
   DexCacheOffsets() : CheckOffsets<mirror::DexCache>(false, "Ljava/lang/DexCache;") {
+    addOffset(OFFSETOF_MEMBER(mirror::DexCache, class_loader_), "classLoader");
     addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile");
     addOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location");
     addOffset(OFFSETOF_MEMBER(mirror::DexCache, num_preresolved_strings_), "numPreResolvedStrings");
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc
index 0c49b90..eab26d8 100644
--- a/runtime/mirror/dex_cache.cc
+++ b/runtime/mirror/dex_cache.cc
@@ -279,6 +279,10 @@
   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
 }
 
+void DexCache::SetClassLoader(ObjPtr<ClassLoader> class_loader) {
+  SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_), class_loader);
+}
+
 #if !defined(__aarch64__) && !defined(__x86_64__)
 static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
 
diff --git a/runtime/mirror/dex_cache.h b/runtime/mirror/dex_cache.h
index 9dc029b..6067c76 100644
--- a/runtime/mirror/dex_cache.h
+++ b/runtime/mirror/dex_cache.h
@@ -44,6 +44,7 @@
 
 class CallSite;
 class Class;
+class ClassLoader;
 class MethodType;
 class String;
 
@@ -479,6 +480,8 @@
 
   void VisitReflectiveTargets(ReflectiveValueVisitor* visitor) REQUIRES(Locks::mutator_lock_);
 
+  void SetClassLoader(ObjPtr<ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_);
+
  private:
   void Init(const DexFile* dex_file,
             ObjPtr<String> location,
@@ -559,10 +562,8 @@
   static void AtomicStoreRelease16B(std::atomic<ConversionPair64>* target, ConversionPair64 value);
 #endif
 
+  HeapReference<ClassLoader> class_loader_;
   HeapReference<String> location_;
-  // Number of elements in the preresolved_strings_ array. Note that this appears here because of
-  // our packing logic for 32 bit fields.
-  uint32_t num_preresolved_strings_;
 
   uint64_t dex_file_;                // const DexFile*
   uint64_t preresolved_strings_;     // GcRoot<mirror::String*> array with num_preresolved_strings
@@ -578,6 +579,7 @@
   uint64_t strings_;                 // std::atomic<StringDexCachePair>*, array with num_strings_
                                      // elements.
 
+  uint32_t num_preresolved_strings_;    // Number of elements in the preresolved_strings_ array.
   uint32_t num_resolved_call_sites_;    // Number of elements in the call_sites_ array.
   uint32_t num_resolved_fields_;        // Number of elements in the resolved_fields_ array.
   uint32_t num_resolved_method_types_;  // Number of elements in the resolved_method_types_ array.