Ensure void type is resolved when running without image

To initialize java.lang.Void correctly, we need to ensure the 'void'
class is initialized in the dex cache of core-libart (because Java
code relies on it). However, if we run without image, the dex cache
may not contain the void class before we initialize java.lang.Void
class.

This CL fixes this by forcing the resolution of 'void' class when
initializing the runtime without image.

We also generalize that to other types by not skipping verification
when running with preopted oat files without image. By verifying
all classes, we ensure all resolved types are in the dex caches.

Bug: 18338511
(cherry picked from commit cad417c72cc879ae8b6a8b2fff26f05a770f2051)

Change-Id: I65e345da47be6eda1ee55897c01a9a4cc1444915
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 1f4cf8f..609478d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -575,6 +575,23 @@
                FindSystemClass(self, "[Ljava/lang/StackTraceElement;"));
   mirror::StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
 
+  // Ensure void type is resolved in the core's dex cache so java.lang.Void is correctly
+  // initialized.
+  {
+    const DexFile& dex_file = java_lang_Object->GetDexFile();
+    const DexFile::StringId* void_string_id = dex_file.FindStringId("V");
+    CHECK(void_string_id != nullptr);
+    uint32_t void_string_index = dex_file.GetIndexForStringId(*void_string_id);
+    const DexFile::TypeId* void_type_id = dex_file.FindTypeId(void_string_index);
+    CHECK(void_type_id != nullptr);
+    uint16_t void_type_idx = dex_file.GetIndexForTypeId(*void_type_id);
+    // Now we resolve void type so the dex cache contains it. We use java.lang.Object class
+    // as referrer so the used dex cache is core's one.
+    mirror::Class* resolved_type = ResolveType(dex_file, void_type_idx, java_lang_Object.Get());
+    CHECK_EQ(resolved_type, GetClassRoot(kPrimitiveVoid));
+    self->AssertNoPendingException();
+  }
+
   FinishInit(self);
 
   VLOG(startup) << "ClassLinker::InitFromCompiler exiting";
@@ -3710,6 +3727,14 @@
     return false;
   }
 
+  // We may be running with a preopted oat file but without image. In this case,
+  // we don't skip verification of preverified classes to ensure we initialize
+  // dex caches with all types resolved during verification.
+  if (!Runtime::Current()->IsCompiler() &&
+      !Runtime::Current()->GetHeap()->HasImageSpace()) {
+    return false;
+  }
+
   uint16_t class_def_index = klass->GetDexClassDefIndex();
   oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus();
   if (oat_file_class_status == mirror::Class::kStatusVerified ||