diff options
Diffstat (limited to 'runtime/native/java_lang_VMClassLoader.cc')
-rw-r--r-- | runtime/native/java_lang_VMClassLoader.cc | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index 4f3e99095b..ee40eb1005 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -18,6 +18,7 @@ #include "base/zip_archive.h" #include "class_linker.h" +#include "class_root-inl.h" #include "dex/descriptors_names.h" #include "dex/dex_file_loader.h" #include "dex/utf.h" @@ -25,6 +26,7 @@ #include "jni/jni_internal.h" #include "mirror/class_loader.h" #include "mirror/object-inl.h" +#include "mirror/object_array-alloc-inl.h" #include "native_util.h" #include "nativehelper/jni_macros.h" #include "nativehelper/scoped_local_ref.h" @@ -129,28 +131,52 @@ static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoa * Returns an array of entries from the boot classpath that could contain resources. */ static jobjectArray VMClassLoader_getBootClassPathEntries(JNIEnv* env, jclass) { - const std::vector<const DexFile*>& path = - Runtime::Current()->GetClassLinker()->GetBootClassPath(); - jobjectArray array = - env->NewObjectArray(path.size(), WellKnownClasses::java_lang_String, nullptr); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + const std::vector<const DexFile*>& path = class_linker->GetBootClassPath(); + auto is_base_dex = [](const DexFile* dex_file) { + return !DexFileLoader::IsMultiDexLocation(dex_file->GetLocation().c_str()); + }; + size_t jar_count = std::count_if(path.begin(), path.end(), is_base_dex); + Thread* self = down_cast<JNIEnvExt*>(env)->GetSelf(); + ScopedObjectAccess soa(self); + StackHandleScope<1u> hs(self); + Handle<mirror::ObjectArray<mirror::String>> array = hs.NewHandle( + mirror::ObjectArray<mirror::String>::Alloc( + self, GetClassRoot<mirror::ObjectArray<mirror::String>>(class_linker), jar_count)); if (array == nullptr) { - DCHECK(env->ExceptionCheck()); + DCHECK(self->IsExceptionPending()); return nullptr; } - for (size_t i = 0; i < path.size(); ++i) { + size_t pos = 0; + for (size_t i = 0, size = path.size(); i != size; ++i) { const DexFile* dex_file = path[i]; // For multidex locations, e.g., x.jar!classes2.dex, we want to look into x.jar. - const std::string location(DexFileLoader::GetBaseLocation(dex_file->GetLocation())); + // But we do not need to look into the base dex file more than once so we filter + // out multidex locations using the fact that they follow the base location. + if (!is_base_dex(dex_file)) { + DCHECK_NE(i, 0u); + DCHECK_EQ(DexFileLoader::GetBaseLocation(dex_file->GetLocation().c_str()), + DexFileLoader::GetBaseLocation(path[i - 1u]->GetLocation().c_str())); + continue; + } - ScopedLocalRef<jstring> javaPath(env, env->NewStringUTF(location.c_str())); - if (javaPath.get() == nullptr) { - DCHECK(env->ExceptionCheck()); + DCHECK_EQ(DexFileLoader::GetBaseLocation(dex_file->GetLocation().c_str()), + dex_file->GetLocation()); + ObjPtr<mirror::String> java_path = + mirror::String::AllocFromModifiedUtf8(self, dex_file->GetLocation().c_str()); + if (java_path == nullptr) { + DCHECK(self->IsExceptionPending()); return nullptr; } - env->SetObjectArrayElement(array, i, javaPath.get()); + // We're initializing a newly allocated array object, so we do not need to record that under + // a transaction. If the transaction is aborted, the whole object shall be unreachable. + array->SetWithoutChecks</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>( + pos, java_path); + ++pos; } - return array; + DCHECK_EQ(pos, jar_count); + return soa.AddLocalReference<jobjectArray>(array.Get()); } static JNINativeMethod gMethods[] = { |