From 3138584a720b86f2f542160425d3a922920760c0 Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Tue, 9 Dec 2014 19:08:15 +0100 Subject: [PATCH] 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 --- runtime/class_linker.cc | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 1f4cf8fcf..609478d12 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -575,6 +575,23 @@ void ClassLinker::InitWithoutImage(const std::vector& boot_class 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 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class 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 || -- 2.11.0