summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--openjdkjvmti/ti_redefine.cc13
-rw-r--r--runtime/class_linker.cc119
-rw-r--r--runtime/class_linker.h15
-rw-r--r--runtime/class_table.cc2
-rw-r--r--runtime/class_table.h7
-rw-r--r--runtime/mirror/class-inl.h12
-rw-r--r--runtime/mirror/class.cc2
-rw-r--r--runtime/mirror/class.h5
-rw-r--r--runtime/native/dalvik_system_DexFile.cc6
-rw-r--r--runtime/native/java_lang_VMClassLoader.cc7
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) {