diff options
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 13 | ||||
-rw-r--r-- | runtime/class_linker.cc | 119 | ||||
-rw-r--r-- | runtime/class_linker.h | 15 | ||||
-rw-r--r-- | runtime/class_table.cc | 2 | ||||
-rw-r--r-- | runtime/class_table.h | 7 | ||||
-rw-r--r-- | runtime/mirror/class-inl.h | 12 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/class.h | 5 | ||||
-rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 6 | ||||
-rw-r--r-- | runtime/native/java_lang_VMClassLoader.cc | 7 |
10 files changed, 110 insertions, 78 deletions
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 0ba528a0a7..19e9adff57 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -1095,14 +1095,13 @@ bool Redefiner::ClassRedefinition::CheckClass() { // Check class name. // These should have been checked by the dexfile verifier on load. DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index"; - const char* descriptor = dex_file_->GetTypeDescriptor(def.class_idx_); - DCHECK(descriptor != nullptr) << "Invalid dex file structure!"; + const std::string_view descriptor = dex_file_->GetTypeDescriptorView(def.class_idx_); if (!current_class->DescriptorEquals(descriptor)) { std::string storage; RecordFailure(ERR(NAMES_DONT_MATCH), StringPrintf("expected file to contain class called '%s' but found '%s'!", current_class->GetDescriptor(&storage), - descriptor)); + std::string(descriptor).c_str())); return false; } if (current_class->IsObjectClass()) { @@ -1111,8 +1110,7 @@ bool Redefiner::ClassRedefinition::CheckClass() { return false; } } else { - const char* super_descriptor = dex_file_->GetTypeDescriptor(def.superclass_idx_); - DCHECK(descriptor != nullptr) << "Invalid dex file structure!"; + const std::string_view super_descriptor = dex_file_->GetTypeDescriptorView(def.superclass_idx_); if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) { RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed"); return false; @@ -1136,9 +1134,8 @@ bool Redefiner::ClassRedefinition::CheckClass() { // The order of interfaces is (barely) meaningful so we error if it changes. const art::DexFile& orig_dex_file = current_class->GetDexFile(); for (uint32_t i = 0; i < interfaces->Size(); i++) { - if (strcmp( - dex_file_->GetTypeDescriptor(interfaces->GetTypeItem(i).type_idx_), - orig_dex_file.GetTypeDescriptor(current_interfaces->GetTypeItem(i).type_idx_)) != 0) { + if (dex_file_->GetTypeDescriptorView(interfaces->GetTypeItem(i).type_idx_) != + orig_dex_file.GetTypeDescriptorView(current_interfaces->GetTypeItem(i).type_idx_)) { RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces changed or re-ordered"); return false; diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 991673f966..2d3217be2e 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2893,7 +2893,7 @@ ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTr } ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self, - const char* descriptor, + std::string_view descriptor, ObjPtr<mirror::Class> klass) { DCHECK(klass != nullptr); if (kIsDebugBuild) { @@ -2972,8 +2972,9 @@ ObjPtr<mirror::Class> ClassLinker::EnsureResolved(Thread* self, using ClassPathEntry = std::pair<const DexFile*, const dex::ClassDef*>; // Search a collection of DexFiles for a descriptor -ClassPathEntry FindInClassPath(const char* descriptor, - size_t hash, const std::vector<const DexFile*>& class_path) { +ClassPathEntry FindInClassPath(std::string_view descriptor, + size_t hash, + const std::vector<const DexFile*>& class_path) { for (const DexFile* dex_file : class_path) { DCHECK(dex_file != nullptr); const dex::ClassDef* dex_class_def = OatDexFile::FindClassDef(*dex_file, descriptor, hash); @@ -3006,15 +3007,18 @@ do { \ bool ClassLinker::FindClassInSharedLibraries(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { ArtField* field = WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoaders; - return FindClassInSharedLibrariesHelper(self, descriptor, hash, class_loader, field, result); + return FindClassInSharedLibrariesHelper( + self, descriptor, descriptor_length, hash, class_loader, field, result); } bool ClassLinker::FindClassInSharedLibrariesHelper(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, ArtField* field, @@ -3031,7 +3035,8 @@ bool ClassLinker::FindClassInSharedLibrariesHelper(Thread* self, for (auto loader : shared_libraries.Iterate<mirror::ClassLoader>()) { temp_loader.Assign(loader); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoader(self, descriptor, hash, temp_loader, result), + FindClassInBaseDexClassLoader( + self, descriptor, descriptor_length, hash, temp_loader, result), *result, self); } @@ -3040,22 +3045,27 @@ bool ClassLinker::FindClassInSharedLibrariesHelper(Thread* self, bool ClassLinker::FindClassInSharedLibrariesAfter(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { ArtField* field = WellKnownClasses::dalvik_system_BaseDexClassLoader_sharedLibraryLoadersAfter; - return FindClassInSharedLibrariesHelper(self, descriptor, hash, class_loader, field, result); + return FindClassInSharedLibrariesHelper( + self, descriptor, descriptor_length, hash, class_loader, field, result); } bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { // Termination case: boot class loader. if (IsBootClassLoader(class_loader.Get())) { RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBootClassLoaderClassPath(self, descriptor, hash, result), *result, self); + FindClassInBootClassLoaderClassPath(self, descriptor, descriptor_length, hash, result), + *result, + self); return true; } @@ -3069,19 +3079,21 @@ bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent())); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoader(self, descriptor, hash, h_parent, result), + FindClassInBaseDexClassLoader(self, descriptor, descriptor_length, hash, h_parent, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibraries(self, descriptor, hash, class_loader, result), + FindClassInSharedLibraries(self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoaderClassPath(self, descriptor, hash, class_loader, result), + FindClassInBaseDexClassLoaderClassPath( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibrariesAfter(self, descriptor, hash, class_loader, result), + FindClassInSharedLibrariesAfter( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); // We did not find a class, but the class loader chain was recognized, so we @@ -3096,17 +3108,21 @@ bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, // - class loader dex files // - parent RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBootClassLoaderClassPath(self, descriptor, hash, result), *result, self); + FindClassInBootClassLoaderClassPath(self, descriptor, descriptor_length, hash, result), + *result, + self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibraries(self, descriptor, hash, class_loader, result), + FindClassInSharedLibraries(self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoaderClassPath(self, descriptor, hash, class_loader, result), + FindClassInBaseDexClassLoaderClassPath( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInSharedLibrariesAfter(self, descriptor, hash, class_loader, result), + FindClassInSharedLibrariesAfter( + self, descriptor, descriptor_length, hash, class_loader, result), *result, self); @@ -3114,7 +3130,7 @@ bool ClassLinker::FindClassInBaseDexClassLoader(Thread* self, StackHandleScope<1> hs(self); Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent())); RETURN_IF_UNRECOGNIZED_OR_FOUND_OR_EXCEPTION( - FindClassInBaseDexClassLoader(self, descriptor, hash, h_parent, result), + FindClassInBaseDexClassLoader(self, descriptor, descriptor_length, hash, h_parent, result), *result, self); // We did not find a class, but the class loader chain was recognized, so we @@ -3158,16 +3174,19 @@ ALWAYS_INLINE void FilterDexFileCaughtExceptions(Thread* self, ClassLinker* clas // If the class is found the method returns the resolved class. Otherwise it returns null. bool ClassLinker::FindClassInBootClassLoaderClassPath(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, /*out*/ ObjPtr<mirror::Class>* result) { - ClassPathEntry pair = FindInClassPath(descriptor, hash, boot_class_path_); + std::string_view sv_descriptor(descriptor, descriptor_length); + ClassPathEntry pair = FindInClassPath(sv_descriptor, hash, boot_class_path_); if (pair.second != nullptr) { - ObjPtr<mirror::Class> klass = LookupClass(self, descriptor, hash, nullptr); + ObjPtr<mirror::Class> klass = LookupClass(self, sv_descriptor, hash, nullptr); if (klass != nullptr) { - *result = EnsureResolved(self, descriptor, klass); + *result = EnsureResolved(self, sv_descriptor, klass); } else { *result = DefineClass(self, descriptor, + descriptor_length, hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, @@ -3185,6 +3204,7 @@ bool ClassLinker::FindClassInBootClassLoaderClassPath(Thread* self, bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) { @@ -3193,11 +3213,12 @@ bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( IsDelegateLastClassLoader(class_loader)) << "Unexpected class loader for descriptor " << descriptor; + std::string_view sv_descriptor(descriptor, descriptor_length); const DexFile* dex_file = nullptr; const dex::ClassDef* class_def = nullptr; ObjPtr<mirror::Class> ret; auto find_class_def = [&](const DexFile* cp_dex_file) REQUIRES_SHARED(Locks::mutator_lock_) { - const dex::ClassDef* cp_class_def = OatDexFile::FindClassDef(*cp_dex_file, descriptor, hash); + const dex::ClassDef* cp_class_def = OatDexFile::FindClassDef(*cp_dex_file, sv_descriptor, hash); if (cp_class_def != nullptr) { dex_file = cp_dex_file; class_def = cp_class_def; @@ -3208,7 +3229,8 @@ bool ClassLinker::FindClassInBaseDexClassLoaderClassPath( VisitClassLoaderDexFiles(self, class_loader, find_class_def); if (class_def != nullptr) { - *result = DefineClass(self, descriptor, hash, class_loader, *dex_file, *class_def); + *result = + DefineClass(self, descriptor, descriptor_length, hash, class_loader, *dex_file, *class_def); if (UNLIKELY(*result == nullptr)) { CHECK(self->IsExceptionPending()) << descriptor; FilterDexFileCaughtExceptions(self, this); @@ -3232,11 +3254,12 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, // for primitive classes that aren't backed by dex files. return FindPrimitiveClass(descriptor[0]); } - const size_t hash = ComputeModifiedUtf8Hash(descriptor); + const std::string_view sv_descriptor(descriptor); + const size_t hash = ComputeModifiedUtf8Hash(sv_descriptor); // Find the class in the loaded classes table. - ObjPtr<mirror::Class> klass = LookupClass(self, descriptor, hash, class_loader.Get()); + ObjPtr<mirror::Class> klass = LookupClass(self, sv_descriptor, hash, class_loader.Get()); if (klass != nullptr) { - return EnsureResolved(self, descriptor, klass); + return EnsureResolved(self, sv_descriptor, klass); } // Class is not yet loaded. if (descriptor[0] != '[' && class_loader == nullptr) { @@ -3245,6 +3268,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, if (pair.second != nullptr) { return DefineClass(self, descriptor, + sv_descriptor.length(), hash, ScopedNullHandle<mirror::ClassLoader>(), *pair.first, @@ -3264,18 +3288,18 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, if (descriptor[0] == '[') { result_ptr = CreateArrayClass(self, descriptor, hash, class_loader); DCHECK_EQ(result_ptr == nullptr, self->IsExceptionPending()); - DCHECK(result_ptr == nullptr || result_ptr->DescriptorEquals(descriptor)); + DCHECK(result_ptr == nullptr || result_ptr->DescriptorEquals(sv_descriptor)); descriptor_equals = true; } else { ScopedObjectAccessUnchecked soa(self); - bool known_hierarchy = - FindClassInBaseDexClassLoader(self, descriptor, hash, class_loader, &result_ptr); + bool known_hierarchy = FindClassInBaseDexClassLoader( + self, descriptor, sv_descriptor.length(), hash, class_loader, &result_ptr); if (result_ptr != nullptr) { // The chain was understood and we found the class. We still need to add the class to // the class table to protect from racy programs that can try and redefine the path list // which would change the Class<?> returned for subsequent evaluation of const-class. DCHECK(known_hierarchy); - DCHECK(result_ptr->DescriptorEquals(descriptor)); + DCHECK(result_ptr->DescriptorEquals(sv_descriptor)); descriptor_equals = true; } else if (!self->IsExceptionPending()) { // Either the chain wasn't understood or the class wasn't found. @@ -3304,15 +3328,14 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, // when native code erroneously calls JNI GetFieldId() with signature "java/lang/String" // instead of "Ljava/lang/String;", the message below using the "dot" names would be // "class loader [...] returned class java.lang.String instead of java.lang.String". - size_t descriptor_length = strlen(descriptor); if (UNLIKELY(descriptor[0] != 'L') || - UNLIKELY(descriptor[descriptor_length - 1] != ';') || - UNLIKELY(memchr(descriptor + 1, '.', descriptor_length - 2) != nullptr)) { + UNLIKELY(descriptor[sv_descriptor.length() - 1] != ';') || + UNLIKELY(memchr(descriptor + 1, '.', sv_descriptor.length() - 2) != nullptr)) { ThrowNoClassDefFoundError("Invalid descriptor: %s.", descriptor); return nullptr; } - std::string class_name_string(descriptor + 1, descriptor_length - 2); + std::string class_name_string(sv_descriptor.substr(1u, sv_descriptor.length() - 2u)); std::replace(class_name_string.begin(), class_name_string.end(), '/', '.'); if (known_hierarchy && fast_class_not_found_exceptions_ && @@ -3342,7 +3365,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, return nullptr; } // Check the name of the returned class. - descriptor_equals = (result_ptr != nullptr) && result_ptr->DescriptorEquals(descriptor); + descriptor_equals = (result_ptr != nullptr) && result_ptr->DescriptorEquals(sv_descriptor); } } else { DCHECK(!MatchesDexFileCaughtExceptions(self->GetException(), this)); @@ -3352,10 +3375,10 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, if (self->IsExceptionPending()) { // If the ClassLoader threw or array class allocation failed, pass that exception up. // However, to comply with the RI behavior, first check if another thread succeeded. - result_ptr = LookupClass(self, descriptor, hash, class_loader.Get()); + result_ptr = LookupClass(self, sv_descriptor, hash, class_loader.Get()); if (result_ptr != nullptr && !result_ptr->IsErroneous()) { self->ClearException(); - return EnsureResolved(self, descriptor, result_ptr); + return EnsureResolved(self, sv_descriptor, result_ptr); } return nullptr; } @@ -3365,7 +3388,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, { WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); ClassTable* const class_table = InsertClassTableForClassLoader(class_loader.Get()); - old = class_table->Lookup(descriptor, hash); + old = class_table->Lookup(sv_descriptor, hash); if (old == nullptr) { old = result_ptr; // For the comparison below, after releasing the lock. if (descriptor_equals) { @@ -3383,7 +3406,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, LOG(WARNING) << "Initiating class loader of type " << DescriptorToDot(loader_class_name) << " is not well-behaved; it returned a different Class for racing loadClass(\"" << DescriptorToDot(descriptor) << "\")."; - return EnsureResolved(self, descriptor, old); + return EnsureResolved(self, sv_descriptor, old); } if (UNLIKELY(!descriptor_equals)) { std::string result_storage; @@ -3447,10 +3470,12 @@ struct ScopedDefiningClass { ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, const dex::ClassDef& dex_class_def) { + std::string_view sv_descriptor(descriptor, descriptor_length); ScopedDefiningClass sdc(self); StackHandleScope<3> hs(self); metrics::AutoTimer timer{GetMetrics()->ClassLoadingTotalTime()}; @@ -3460,17 +3485,17 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, // Load the class from the dex file. if (UNLIKELY(!init_done_)) { // finish up init of hand crafted class_roots_ - if (strcmp(descriptor, "Ljava/lang/Object;") == 0) { + if (sv_descriptor == "Ljava/lang/Object;") { klass.Assign(GetClassRoot<mirror::Object>(this)); - } else if (strcmp(descriptor, "Ljava/lang/Class;") == 0) { + } else if (sv_descriptor == "Ljava/lang/Class;") { klass.Assign(GetClassRoot<mirror::Class>(this)); - } else if (strcmp(descriptor, "Ljava/lang/String;") == 0) { + } else if (sv_descriptor == "Ljava/lang/String;") { klass.Assign(GetClassRoot<mirror::String>(this)); - } else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) { + } else if (sv_descriptor == "Ljava/lang/ref/Reference;") { klass.Assign(GetClassRoot<mirror::Reference>(this)); - } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) { + } else if (sv_descriptor == "Ljava/lang/DexCache;") { klass.Assign(GetClassRoot<mirror::DexCache>(this)); - } else if (strcmp(descriptor, "Ldalvik/system/ClassExt;") == 0) { + } else if (sv_descriptor == "Ldalvik/system/ClassExt;") { klass.Assign(GetClassRoot<mirror::ClassExt>(this)); } } @@ -3544,7 +3569,7 @@ ObjPtr<mirror::Class> ClassLinker::DefineClass(Thread* self, // Mark the string class by setting its access flag. if (UNLIKELY(!init_done_)) { - if (strcmp(descriptor, "Ljava/lang/String;") == 0) { + if (sv_descriptor == "Ljava/lang/String;") { klass->SetStringClass(); } } @@ -4733,7 +4758,7 @@ ObjPtr<mirror::Class> ClassLinker::FindPrimitiveClass(char type) { return result; } -ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor, +ObjPtr<mirror::Class> ClassLinker::InsertClass(std::string_view descriptor, ObjPtr<mirror::Class> klass, size_t hash) { DCHECK(Thread::Current()->CanLoadClasses()); @@ -4786,13 +4811,13 @@ void ClassLinker::UpdateClassMethods(ObjPtr<mirror::Class> klass, } ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self, - const char* descriptor, + std::string_view descriptor, ObjPtr<mirror::ClassLoader> class_loader) { return LookupClass(self, descriptor, ComputeModifiedUtf8Hash(descriptor), class_loader); } ObjPtr<mirror::Class> ClassLinker::LookupClass(Thread* self, - const char* descriptor, + std::string_view descriptor, size_t hash, ObjPtr<mirror::ClassLoader> class_loader) { ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 35cdfbcdd3..ef8241ad2f 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -232,6 +232,7 @@ class ClassLinker { // Define a new a class based on a ClassDef from a DexFile ObjPtr<mirror::Class> DefineClass(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file, @@ -242,7 +243,7 @@ class ClassLinker { // Finds a class by its descriptor, returning null if it isn't wasn't loaded // by the given 'class_loader'. EXPORT ObjPtr<mirror::Class> LookupClass(Thread* self, - const char* descriptor, + std::string_view descriptor, ObjPtr<mirror::ClassLoader> class_loader) REQUIRES(!Locks::classlinker_classes_lock_) REQUIRES_SHARED(Locks::mutator_lock_); @@ -659,7 +660,7 @@ class ClassLinker { // Attempts to insert a class into a class table. Returns null if // the class was inserted, otherwise returns an existing class with // the same descriptor and ClassLoader. - ObjPtr<mirror::Class> InsertClass(const char* descriptor, + ObjPtr<mirror::Class> InsertClass(std::string_view descriptor, ObjPtr<mirror::Class> klass, size_t hash) REQUIRES(!Locks::classlinker_classes_lock_) @@ -1135,6 +1136,7 @@ class ClassLinker { // PathClassLoader are supported). bool FindClassInBaseDexClassLoader(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) @@ -1143,6 +1145,7 @@ class ClassLinker { bool FindClassInSharedLibraries(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) @@ -1151,6 +1154,7 @@ class ClassLinker { bool FindClassInSharedLibrariesHelper(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, ArtField* field, @@ -1160,6 +1164,7 @@ class ClassLinker { bool FindClassInSharedLibrariesAfter(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) @@ -1176,6 +1181,7 @@ class ClassLinker { bool FindClassInBaseDexClassLoaderClassPath( Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader, /*out*/ ObjPtr<mirror::Class>* result) @@ -1188,6 +1194,7 @@ class ClassLinker { // boot class loader has a known lookup. bool FindClassInBootClassLoaderClassPath(Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, /*out*/ ObjPtr<mirror::Class>* result) REQUIRES_SHARED(Locks::mutator_lock_) @@ -1230,7 +1237,7 @@ class ClassLinker { // Finds a class by its descriptor, returning NULL if it isn't wasn't loaded // by the given 'class_loader'. Uses the provided hash for the descriptor. ObjPtr<mirror::Class> LookupClass(Thread* self, - const char* descriptor, + std::string_view descriptor, size_t hash, ObjPtr<mirror::ClassLoader> class_loader) REQUIRES(!Locks::classlinker_classes_lock_) @@ -1341,7 +1348,7 @@ class ClassLinker { // retire a class, the version of the class in the table is returned and this may differ from // the class passed in. ObjPtr<mirror::Class> EnsureResolved(Thread* self, - const char* descriptor, + std::string_view descriptor, ObjPtr<mirror::Class> klass) WARN_UNUSED REQUIRES_SHARED(Locks::mutator_lock_) diff --git a/runtime/class_table.cc b/runtime/class_table.cc index 35d3537478..5a20c2f576 100644 --- a/runtime/class_table.cc +++ b/runtime/class_table.cc @@ -104,7 +104,7 @@ size_t ClassTable::NumReferencedNonZygoteClasses() const { return classes_.back().size(); } -ObjPtr<mirror::Class> ClassTable::Lookup(const char* descriptor, size_t hash) { +ObjPtr<mirror::Class> ClassTable::Lookup(std::string_view descriptor, size_t hash) { DescriptorHashPair pair(descriptor, hash); ReaderMutexLock mu(Thread::Current(), lock_); // Search from the last table, assuming that apps shall search for their own classes diff --git a/runtime/class_table.h b/runtime/class_table.h index 3374622f00..64ae758208 100644 --- a/runtime/class_table.h +++ b/runtime/class_table.h @@ -114,14 +114,15 @@ class ClassTable { static constexpr uint32_t kHashMask = kObjectAlignment - 1; }; - using DescriptorHashPair = std::pair<const char*, uint32_t>; + using DescriptorHashPair = std::pair<std::string_view, uint32_t>; class ClassDescriptorHash { public: // uint32_t for cross compilation. + // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions. uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS; // uint32_t for cross compilation. - uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS; + uint32_t operator()(const DescriptorHashPair& pair) const; }; class ClassDescriptorEquals { @@ -221,7 +222,7 @@ class ClassTable { REQUIRES_SHARED(Locks::mutator_lock_); // Return the first class that matches the descriptor. Returns null if there are none. - ObjPtr<mirror::Class> Lookup(const char* descriptor, size_t hash) + ObjPtr<mirror::Class> Lookup(std::string_view descriptor, size_t hash) REQUIRES(!lock_) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index f60a554f91..20b5f463f0 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -959,26 +959,26 @@ inline std::string_view Class::GetDescriptorView() { return GetDexFile().GetTypeDescriptorView(GetDexTypeIndex()); } -inline bool Class::DescriptorEquals(const char* match) { +inline bool Class::DescriptorEquals(std::string_view match) { ObjPtr<mirror::Class> klass = this; while (klass->IsArrayClass()) { - if (match[0] != '[') { + if (UNLIKELY(match.empty()) || match[0] != '[') { return false; } - ++match; + match.remove_prefix(1u); // No read barrier needed, we're reading a chain of constant references for comparison // with null. Then we follow up below with reading constant references to read constant // primitive data in both proxy and non-proxy paths. See ReadBarrierOption. klass = klass->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>(); } if (klass->IsPrimitive()) { - return strcmp(Primitive::Descriptor(klass->GetPrimitiveType()), match) == 0; - } else if (klass->IsProxyClass()) { + return match.length() == 1u && match[0] == Primitive::Descriptor(klass->GetPrimitiveType())[0]; + } else if (UNLIKELY(klass->IsProxyClass())) { return klass->ProxyDescriptorEquals(match); } else { const DexFile& dex_file = klass->GetDexFile(); const dex::TypeId& type_id = dex_file.GetTypeId(klass->GetDexTypeIndex()); - return strcmp(dex_file.GetTypeDescriptor(type_id), match) == 0; + return dex_file.GetTypeDescriptorView(type_id) == match; } } diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index 43dbc43115..9ca373e0cf 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -1879,7 +1879,7 @@ bool Class::ProxyDescriptorEquals(ObjPtr<mirror::Class> match) { return descriptor == match_descriptor; } -bool Class::ProxyDescriptorEquals(const char* match) { +bool Class::ProxyDescriptorEquals(std::string_view match) { DCHECK(IsProxyClass()); std::string storage; const char* descriptor = GetDescriptor(&storage); diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 6384bfabc0..9560f985ac 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1252,7 +1252,7 @@ class EXPORT MANAGED Class final : public Object { const char* GetDescriptor(std::string* storage) REQUIRES_SHARED(Locks::mutator_lock_); bool DescriptorEquals(ObjPtr<mirror::Class> match) REQUIRES_SHARED(Locks::mutator_lock_); - bool DescriptorEquals(const char* match) REQUIRES_SHARED(Locks::mutator_lock_); + bool DescriptorEquals(std::string_view match) REQUIRES_SHARED(Locks::mutator_lock_); uint32_t DescriptorHash() REQUIRES_SHARED(Locks::mutator_lock_); @@ -1440,11 +1440,10 @@ class EXPORT MANAGED Class final : public Object { ALWAYS_INLINE uint32_t GetDirectMethodsStartOffset() REQUIRES_SHARED(Locks::mutator_lock_); bool ProxyDescriptorEquals(ObjPtr<mirror::Class> match) REQUIRES_SHARED(Locks::mutator_lock_); - bool ProxyDescriptorEquals(const char* match) REQUIRES_SHARED(Locks::mutator_lock_); + bool ProxyDescriptorEquals(std::string_view match) REQUIRES_SHARED(Locks::mutator_lock_); static uint32_t UpdateHashForProxyClass(uint32_t hash, ObjPtr<mirror::Class> proxy_class) REQUIRES_SHARED(Locks::mutator_lock_); - template<VerifyObjectFlags kVerifyFlags> void GetAccessFlagsDCheck() REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index f7f446542c..a1d4f16d26 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -488,10 +488,9 @@ static jclass DexFile_defineClassNative(JNIEnv* env, return nullptr; } const std::string descriptor(DotToDescriptor(class_name.c_str())); - const size_t hash(ComputeModifiedUtf8Hash(descriptor.c_str())); + const size_t hash = ComputeModifiedUtf8Hash(descriptor); for (auto& dex_file : dex_files) { - const dex::ClassDef* dex_class_def = - OatDexFile::FindClassDef(*dex_file, descriptor.c_str(), hash); + const dex::ClassDef* dex_class_def = OatDexFile::FindClassDef(*dex_file, descriptor, hash); if (dex_class_def != nullptr) { ScopedObjectAccess soa(env); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); @@ -507,6 +506,7 @@ static jclass DexFile_defineClassNative(JNIEnv* env, } ObjPtr<mirror::Class> result = class_linker->DefineClass(soa.Self(), descriptor.c_str(), + descriptor.length(), hash, class_loader, *dex_file, diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index ba1fde00d3..a735765bdd 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -56,11 +56,13 @@ class VMClassLoader { static ObjPtr<mirror::Class> FindClassInPathClassLoader(ClassLinker* cl, Thread* self, const char* descriptor, + size_t descriptor_length, size_t hash, Handle<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_) { ObjPtr<mirror::Class> result; - if (cl->FindClassInBaseDexClassLoader(self, descriptor, hash, class_loader, &result)) { + if (cl->FindClassInBaseDexClassLoader( + self, descriptor, descriptor_length, hash, class_loader, &result)) { DCHECK(!self->IsExceptionPending()); return result; } @@ -83,7 +85,7 @@ static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoa // Compute hash once. std::string descriptor(DotToDescriptor(name.c_str())); - const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str()); + const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor); ObjPtr<mirror::Class> c = VMClassLoader::LookupClass(cl, soa.Self(), @@ -115,6 +117,7 @@ static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoa c = VMClassLoader::FindClassInPathClassLoader(cl, soa.Self(), descriptor.c_str(), + descriptor.length(), descriptor_hash, hs.NewHandle(loader)); if (c != nullptr) { |