diff options
author | Ian Rogers <irogers@google.com> | 2014-11-19 14:05:21 -0800 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-11-19 14:05:21 -0800 |
commit | 3242729362b74d22f11d8bc7b4800ba0a8695df6 (patch) | |
tree | e3ac6dbb1d4f1f6295ed4a856473c6f92c88be22 /runtime | |
parent | 834896de1c955c04d781d2bf8c53573f94ce8c3e (diff) | |
download | art-3242729362b74d22f11d8bc7b4800ba0a8695df6.tar.gz art-3242729362b74d22f11d8bc7b4800ba0a8695df6.tar.bz2 art-3242729362b74d22f11d8bc7b4800ba0a8695df6.zip |
Avoid JNI call with pending OOME.
If EnsureResolved fails with an exception then FindClassInPathClassLoader may
fall-through to a call to NewStringUTF with a pending exception.
Bug: 15446488
Change-Id: I007f7bee7c50aa588d0b1c776da67a38314dc897
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 24 | ||||
-rw-r--r-- | runtime/class_linker.h | 4 |
2 files changed, 17 insertions, 11 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 68e20f2763..e1b79c9f87 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2060,6 +2060,7 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready Thread* self, const char* descriptor, size_t hash, Handle<mirror::ClassLoader> class_loader) { + // Can we special case for a well understood PathClassLoader with the BootClassLoader as parent? if (class_loader->GetClass() != soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader) || class_loader->GetParent()->GetClass() != @@ -2071,17 +2072,21 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready if (pair.second != nullptr) { mirror::Class* klass = LookupClass(self, descriptor, hash, nullptr); if (klass != nullptr) { - return EnsureResolved(self, descriptor, klass); + // May return null if resolution on another thread fails. + klass = EnsureResolved(self, descriptor, klass); + } else { + // May OOME. + klass = DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first, + *pair.second); } - klass = DefineClass(self, descriptor, hash, NullHandle<mirror::ClassLoader>(), *pair.first, - *pair.second); - if (klass != nullptr) { - return klass; + if (klass == nullptr) { + CHECK(self->IsExceptionPending()) << descriptor; + self->ClearException(); } - CHECK(self->IsExceptionPending()) << descriptor; - self->ClearException(); + return klass; } else { - // RegisterDexFile may allocate dex caches (and cause thread suspension). + // Handle as if this is the child PathClassLoader. + // Handles as RegisterDexFile may allocate dex caches (and cause thread suspension). StackHandleScope<3> hs(self); // The class loader is a PathClassLoader which inherits from BaseDexClassLoader. // We need to get the DexPathList and loop through it. @@ -2138,8 +2143,9 @@ mirror::Class* ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlready } } } + self->AssertNoPendingException(); + return nullptr; } - return nullptr; } mirror::Class* ClassLinker::FindClass(Thread* self, const char* descriptor, diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 006354f948..b78d0b5bc3 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -117,8 +117,8 @@ class ClassLinker { Handle<mirror::ClassLoader> class_loader) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Find a class in the path class loader, loading it if necessary. Hash function is supposed to - // be ComputeModifiedUtf8Hash(descriptor). + // Find a class in the path class loader, loading it if necessary without using JNI. Hash + // function is supposed to be ComputeModifiedUtf8Hash(descriptor). mirror::Class* FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& soa, Thread* self, const char* descriptor, size_t hash, Handle<mirror::ClassLoader> class_loader) |