Merge "Ensure void type is resolved when running without image"
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 ||