Pre-resolve dex cache strings before collecting string offsets

Fix a bug where string offsets are nondeterministic in some cases.
This was caused by preresolving strings after collecting string
offsets.

Bug: 120039850
Test: test-art-host

(cherry picked from commit fe0e00a4d683aefa572dcc50b3f87ff77cb5162a)

Merged-In: I39235c6b4fa43a89e7082962d1c7d4643748d078
Change-Id: Ia22cb82fa07091a75a1cfaeb24231ce53d706b35
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index c36f360..9626e21 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -253,6 +253,19 @@
     CheckNonImageClassesRemoved();
   }
 
+  {
+    // Preload deterministic contents to the dex cache arrays we're going to write.
+    ScopedObjectAccess soa(self);
+    ObjPtr<mirror::ClassLoader> class_loader = GetAppClassLoader();
+    std::vector<ObjPtr<mirror::DexCache>> dex_caches = FindDexCaches(self);
+    for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
+      if (!IsImageObject(dex_cache)) {
+        continue;  // Boot image DexCache is not written to the app image.
+      }
+      PreloadDexCache(dex_cache, class_loader);
+    }
+  }
+
   // Used to store information that will later be used to calculate image
   // offsets to string references in the AppImage.
   std::vector<HeapReferencePointerInfo> string_ref_info;
@@ -697,20 +710,7 @@
   CHECK(!oat_filenames.empty());
   CHECK_EQ(image_filenames.size(), oat_filenames.size());
 
-  Thread* self = Thread::Current();
-  {
-    // Preload deterministic contents to the dex cache arrays we're going to write.
-    ScopedObjectAccess soa(self);
-    ObjPtr<mirror::ClassLoader> class_loader = GetAppClassLoader();
-    std::vector<ObjPtr<mirror::DexCache>> dex_caches = FindDexCaches(self);
-    for (ObjPtr<mirror::DexCache> dex_cache : dex_caches) {
-      if (!IsImageObject(dex_cache)) {
-        continue;  // Boot image DexCache is not written to the app image.
-      }
-      PreloadDexCache(dex_cache, class_loader);
-    }
-  }
-
+  Thread* const self = Thread::Current();
   {
     ScopedObjectAccess soa(self);
     for (size_t i = 0; i < oat_filenames.size(); ++i) {