summaryrefslogtreecommitdiff
path: root/runtime/native/java_lang_VMClassLoader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/native/java_lang_VMClassLoader.cc')
-rw-r--r--runtime/native/java_lang_VMClassLoader.cc50
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[] = {