diff options
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 192 |
1 files changed, 62 insertions, 130 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index c667fe2f30..ebac5c1661 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1122,12 +1122,8 @@ static bool FlattenPathClassLoader(ObjPtr<mirror::ClassLoader> class_loader, DCHECK(out_dex_file_names != nullptr); DCHECK(error_msg != nullptr); ScopedObjectAccessUnchecked soa(Thread::Current()); - ArtField* const dex_path_list_field = - jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList); - ArtField* const dex_elements_field = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements); - CHECK(dex_path_list_field != nullptr); - CHECK(dex_elements_field != nullptr); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> handle(hs.NewHandle(class_loader)); while (!ClassLinker::IsBootClassLoader(soa, class_loader)) { if (soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader) != class_loader->GetClass()) { @@ -1136,32 +1132,29 @@ static bool FlattenPathClassLoader(ObjPtr<mirror::ClassLoader> class_loader, // Unsupported class loader. return false; } - ObjPtr<mirror::Object> dex_path_list = dex_path_list_field->GetObject(class_loader); - if (dex_path_list != nullptr) { - // DexPathList has an array dexElements of Elements[] which each contain a dex file. - ObjPtr<mirror::Object> dex_elements_obj = dex_elements_field->GetObject(dex_path_list); - // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look - // at the mCookie which is a DexFile vector. - if (dex_elements_obj != nullptr) { - ObjPtr<mirror::ObjectArray<mirror::Object>> dex_elements = - dex_elements_obj->AsObjectArray<mirror::Object>(); - // Reverse order since we insert the parent at the front. - for (int32_t i = dex_elements->GetLength() - 1; i >= 0; --i) { - ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); - if (element == nullptr) { - *error_msg = StringPrintf("Null dex element at index %d", i); - return false; - } - ObjPtr<mirror::String> name; - if (!GetDexPathListElementName(element, &name)) { - *error_msg = StringPrintf("Invalid dex path list element at index %d", i); - return false; - } - if (name != nullptr) { - out_dex_file_names->push_front(name.Ptr()); - } - } + // Get element names. Sets error to true on failure. + auto add_element_names = [&](ObjPtr<mirror::Object> element, bool* error) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (element == nullptr) { + *error_msg = "Null dex element"; + *error = true; // Null element is a critical error. + return false; // Had an error, stop the visit. + } + ObjPtr<mirror::String> name; + if (!GetDexPathListElementName(element, &name)) { + *error_msg = "Invalid dex path list element"; + *error = false; // Invalid element is not a critical error. + return false; // Stop the visit. } + if (name != nullptr) { + out_dex_file_names->push_front(name.Ptr()); + } + return true; // Continue with the next Element. + }; + bool error = VisitClassLoaderDexElements(soa, handle, add_element_names, /* error */ false); + if (error) { + // An error occurred during DexPathList Element visiting. + return false; } class_loader = class_loader->GetParent(); } @@ -2444,71 +2437,33 @@ ObjPtr<mirror::Class> ClassLinker::FindClassInBaseDexClassLoaderClassPath( const char* descriptor, size_t hash, Handle<mirror::ClassLoader> class_loader) { - CHECK(IsPathOrDexClassLoader(soa, class_loader) || IsDelegateLastClassLoader(soa, class_loader)) + DCHECK(IsPathOrDexClassLoader(soa, class_loader) || IsDelegateLastClassLoader(soa, class_loader)) << "Unexpected class loader for descriptor " << descriptor; - Thread* self = soa.Self(); - ArtField* const cookie_field = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); - ArtField* const dex_file_field = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - ObjPtr<mirror::Object> dex_path_list = - jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)-> - GetObject(class_loader.Get()); - if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { - // DexPathList has an array dexElements of Elements[] which each contain a dex file. - ObjPtr<mirror::Object> dex_elements_obj = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> - GetObject(dex_path_list); - // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look - // at the mCookie which is a DexFile vector. - if (dex_elements_obj != nullptr) { - StackHandleScope<1> hs(self); - Handle<mirror::ObjectArray<mirror::Object>> dex_elements = - hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>()); - for (int32_t i = 0; i < dex_elements->GetLength(); ++i) { - ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); - if (element == nullptr) { - // Should never happen, fall back to java code to throw a NPE. - break; - } - ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element); - if (dex_file != nullptr) { - ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray(); - if (long_array == nullptr) { - // This should never happen so log a warning. - LOG(WARNING) << "Null DexFile::mCookie for " << descriptor; - break; - } - int32_t long_array_size = long_array->GetLength(); - // First element is the oat file. - for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) { - const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>( - long_array->GetWithoutChecks(j))); - const DexFile::ClassDef* dex_class_def = - OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash); - if (dex_class_def != nullptr) { - ObjPtr<mirror::Class> klass = DefineClass(self, - descriptor, - hash, - class_loader, - *cp_dex_file, - *dex_class_def); - if (klass == nullptr) { - CHECK(self->IsExceptionPending()) << descriptor; - self->ClearException(); - // TODO: Is it really right to break here, and not check the other dex files? - return nullptr; - } - return klass; - } - } - } - } - } - self->AssertNoPendingException(); - } - return nullptr; + ObjPtr<mirror::Class> ret; + auto define_class = [&](const DexFile* cp_dex_file) REQUIRES_SHARED(Locks::mutator_lock_) { + const DexFile::ClassDef* dex_class_def = + OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash); + if (dex_class_def != nullptr) { + ObjPtr<mirror::Class> klass = DefineClass(soa.Self(), + descriptor, + hash, + class_loader, + *cp_dex_file, + *dex_class_def); + if (klass == nullptr) { + CHECK(soa.Self()->IsExceptionPending()) << descriptor; + soa.Self()->ClearException(); + // TODO: Is it really right to break here, and not check the other dex files? + } + ret = klass; + return false; // Found a Class (or error == nullptr), stop visit. + } + return true; // Continue with the next DexFile. + }; + + VisitClassLoaderDexFiles(soa, class_loader, define_class); + return ret; } mirror::Class* ClassLinker::FindClass(Thread* self, @@ -7901,42 +7856,19 @@ std::string DescribeLoaders(ObjPtr<mirror::ClassLoader> loader, const char* clas if (loader->GetClass() == path_class_loader || loader->GetClass() == dex_class_loader || loader->GetClass() == delegate_last_class_loader) { - ArtField* const cookie_field = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie); - ArtField* const dex_file_field = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile); - ObjPtr<mirror::Object> dex_path_list = - jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)-> - GetObject(loader); - if (dex_path_list != nullptr && dex_file_field != nullptr && cookie_field != nullptr) { - ObjPtr<mirror::Object> dex_elements_obj = - jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)-> - GetObject(dex_path_list); - if (dex_elements_obj != nullptr) { - ObjPtr<mirror::ObjectArray<mirror::Object>> dex_elements = - dex_elements_obj->AsObjectArray<mirror::Object>(); - oss << "("; - const char* path_separator = ""; - for (int32_t i = 0; i != dex_elements->GetLength(); ++i) { - ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i); - ObjPtr<mirror::Object> dex_file = - (element != nullptr) ? dex_file_field->GetObject(element) : nullptr; - ObjPtr<mirror::LongArray> long_array = - (dex_file != nullptr) ? cookie_field->GetObject(dex_file)->AsLongArray() : nullptr; - if (long_array != nullptr) { - int32_t long_array_size = long_array->GetLength(); - // First element is the oat file. - for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) { - const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>( - static_cast<uintptr_t>(long_array->GetWithoutChecks(j))); - oss << path_separator << cp_dex_file->GetLocation(); - path_separator = ":"; - } - } - } - oss << ")"; - } - } + oss << "("; + ScopedObjectAccessUnchecked soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> handle(hs.NewHandle(loader)); + const char* path_separator = ""; + VisitClassLoaderDexFiles(soa, + handle, + [&](const DexFile* dex_file) { + oss << path_separator << dex_file->GetLocation(); + path_separator = ":"; + return true; // Continue with the next DexFile. + }); + oss << ")"; } } |